Implement QStringRef::split

[ChangeLog][QtCore] Added the QStringRef::split() function

Change-Id: I28709c9761785dea7be4e7d621ecf4e1ae007a72
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Jędrzej Nowacki 2014-05-14 16:56:10 +02:00
parent fc16dcce9d
commit 1fceabe8c7
3 changed files with 113 additions and 2 deletions

View File

@ -6625,8 +6625,8 @@ QString QString::number(double n, char f, int prec)
}
namespace {
template<class ResultList, typename MidMethod, typename Separator>
static ResultList splitString(const QString &source, MidMethod mid, const Separator &sep,
template<class ResultList, class StringSource, typename MidMethod, typename Separtor>
static ResultList splitString(const StringSource &source, MidMethod mid, const Separtor &sep,
QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize)
{
ResultList list;
@ -6707,6 +6707,37 @@ QVector<QStringRef> QString::splitRef(QChar sep, SplitBehavior behavior, Qt::Cas
return splitString<QVector<QStringRef> >(*this, &QString::midRef, sep, behavior, cs, 1);
}
/*!
Splits the string into substrings references wherever \a sep occurs, and
returns the list of those strings. If \a sep does not match
anywhere in the string, split() 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
*/
QVector<QStringRef> QStringRef::split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
return splitString<QVector<QStringRef> >(*this, &QStringRef::mid, sep, behavior, cs, sep.size());
}
/*!
\overload
\since 5.4
*/
QVector<QStringRef> QStringRef::split(QChar sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
return splitString<QVector<QStringRef> >(*this, &QStringRef::mid, sep, behavior, cs, 1);
}
#ifndef QT_NO_REGEXP
namespace {
template<class ResultList, typename MidMethod>

View File

@ -1305,6 +1305,11 @@ public:
int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QVector<QStringRef> split(const QString &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QVector<QStringRef> split(QChar sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QStringRef left(int n) const Q_REQUIRED_RESULT;
QStringRef right(int n) const Q_REQUIRED_RESULT;
QStringRef mid(int pos, int n = -1) const Q_REQUIRED_RESULT;

View File

@ -93,6 +93,8 @@ private slots:
void left();
void right();
void mid();
void split_data();
void split();
};
static QStringRef emptyRef()
@ -1984,6 +1986,79 @@ void tst_QStringRef::mid()
QVERIFY(emptyRef.mid(-10, 3).isEmpty());
}
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; }
void tst_QStringRef::split_data()
{
QTest::addColumn<QString>("str");
QTest::addColumn<QString>("sep");
QTest::addColumn<QStringList>("result");
QTest::newRow("a,b,c") << "a,b,c" << "," << (QStringList() << "a" << "b" << "c");
QTest::newRow("a,b,c,a,b,c") << "a,b,c,a,b,c" << "," << (QStringList() << "a" << "b" << "c" << "a" << "b" << "c");
QTest::newRow("a,b,c,,a,b,c") << "a,b,c,,a,b,c" << "," << (QStringList() << "a" << "b" << "c" << "" << "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("all-null") << QString() << QString() << (QStringList() << QString() << QString());
QTest::newRow("sep-empty") << "abc" << "" << (QStringList() << "" << "a" << "b" << "c" << "");
}
void tst_QStringRef::split()
{
QFETCH(QString, str);
QFETCH(QString, sep);
QFETCH(QStringList, result);
QVector<QStringRef> list;
// we construct a bigger valid string to check
// if ref.split is using the right size
QString source = str + str + str;
QStringRef ref = source.midRef(str.size(), str.size());
QCOMPARE(ref.size(), str.size());
list = ref.split(sep);
QVERIFY(list == result);
if (sep.size() == 1) {
list = ref.split(sep.at(0));
QVERIFY(list == result);
}
list = ref.split(sep, QString::KeepEmptyParts);
QVERIFY(list == result);
if (sep.size() == 1) {
list = ref.split(sep.at(0), QString::KeepEmptyParts);
QVERIFY(list == result);
}
result.removeAll("");
list = ref.split(sep, QString::SkipEmptyParts);
QVERIFY(list == result);
if (sep.size() == 1) {
list = ref.split(sep.at(0), QString::SkipEmptyParts);
QVERIFY(list == result);
}
}
QTEST_APPLESS_MAIN(tst_QStringRef)
#include "tst_qstringref.moc"