Move methods using QRegExp in QString(List) over to QRegExp
The prepares for the removal of those methods from QString and QStringList. The new methods in QRegExp are left as a porting help. Change-Id: Ieffa33a79caf53b83029e9b070c4eb5cadca1418 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
7a3a9b8eb5
commit
7370b60cfe
@ -4479,6 +4479,419 @@ int QRegExp::matchedLength() const
|
||||
return priv->matchState.captured[1];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Replaces every occurrence of this regular expression in
|
||||
\a str with \a after and returns the result.
|
||||
|
||||
For regular expressions containing \l{capturing parentheses},
|
||||
occurrences of \b{\\1}, \b{\\2}, ..., in \a after are replaced
|
||||
with \a{rx}.cap(1), cap(2), ...
|
||||
|
||||
\sa indexIn(), lastIndexIn(), QRegExp::cap()
|
||||
*/
|
||||
QString QRegExp::replaceIn(const QString &str, const QString &after) const
|
||||
{
|
||||
struct QStringCapture
|
||||
{
|
||||
int pos;
|
||||
int len;
|
||||
int no;
|
||||
};
|
||||
|
||||
QRegExp rx2(*this);
|
||||
|
||||
if (str.isEmpty() && rx2.indexIn(str) == -1)
|
||||
return str;
|
||||
|
||||
QString s(str);
|
||||
|
||||
int index = 0;
|
||||
int numCaptures = rx2.captureCount();
|
||||
int al = after.length();
|
||||
QRegExp::CaretMode caretMode = QRegExp::CaretAtZero;
|
||||
|
||||
if (numCaptures > 0) {
|
||||
const QChar *uc = after.unicode();
|
||||
int numBackRefs = 0;
|
||||
|
||||
for (int i = 0; i < al - 1; i++) {
|
||||
if (uc[i] == QLatin1Char('\\')) {
|
||||
int no = uc[i + 1].digitValue();
|
||||
if (no > 0 && no <= numCaptures)
|
||||
numBackRefs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is the harder case where we have back-references.
|
||||
*/
|
||||
if (numBackRefs > 0) {
|
||||
QVarLengthArray<QStringCapture, 16> captures(numBackRefs);
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < al - 1; i++) {
|
||||
if (uc[i] == QLatin1Char('\\')) {
|
||||
int no = uc[i + 1].digitValue();
|
||||
if (no > 0 && no <= numCaptures) {
|
||||
QStringCapture capture;
|
||||
capture.pos = i;
|
||||
capture.len = 2;
|
||||
|
||||
if (i < al - 2) {
|
||||
int secondDigit = uc[i + 2].digitValue();
|
||||
if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
|
||||
no = (no * 10) + secondDigit;
|
||||
++capture.len;
|
||||
}
|
||||
}
|
||||
|
||||
capture.no = no;
|
||||
captures[j++] = capture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (index <= s.length()) {
|
||||
index = rx2.indexIn(s, index, caretMode);
|
||||
if (index == -1)
|
||||
break;
|
||||
|
||||
QString after2(after);
|
||||
for (j = numBackRefs - 1; j >= 0; j--) {
|
||||
const QStringCapture &capture = captures[j];
|
||||
after2.replace(capture.pos, capture.len, rx2.cap(capture.no));
|
||||
}
|
||||
|
||||
s.replace(index, rx2.matchedLength(), after2);
|
||||
index += after2.length();
|
||||
|
||||
// avoid infinite loop on 0-length matches (e.g., QRegExp("[a-z]*"))
|
||||
if (rx2.matchedLength() == 0)
|
||||
++index;
|
||||
|
||||
caretMode = QRegExp::CaretWontMatch;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is the simple and optimized case where we don't have
|
||||
back-references.
|
||||
*/
|
||||
while (index != -1) {
|
||||
struct {
|
||||
int pos;
|
||||
int length;
|
||||
} replacements[2048];
|
||||
|
||||
int pos = 0;
|
||||
int adjust = 0;
|
||||
while (pos < 2047) {
|
||||
index = rx2.indexIn(s, index, caretMode);
|
||||
if (index == -1)
|
||||
break;
|
||||
int ml = rx2.matchedLength();
|
||||
replacements[pos].pos = index;
|
||||
replacements[pos++].length = ml;
|
||||
index += ml;
|
||||
adjust += al - ml;
|
||||
// avoid infinite loop
|
||||
if (!ml)
|
||||
index++;
|
||||
}
|
||||
if (!pos)
|
||||
break;
|
||||
replacements[pos].pos = s.size();
|
||||
int newlen = s.size() + adjust;
|
||||
|
||||
// to continue searching at the right position after we did
|
||||
// the first round of replacements
|
||||
if (index != -1)
|
||||
index += adjust;
|
||||
QString newstring;
|
||||
newstring.reserve(newlen + 1);
|
||||
QChar *newuc = newstring.data();
|
||||
QChar *uc = newuc;
|
||||
int copystart = 0;
|
||||
int i = 0;
|
||||
while (i < pos) {
|
||||
int copyend = replacements[i].pos;
|
||||
int size = copyend - copystart;
|
||||
memcpy(static_cast<void*>(uc), static_cast<const void *>(s.constData() + copystart), size * sizeof(QChar));
|
||||
uc += size;
|
||||
memcpy(static_cast<void *>(uc), static_cast<const void *>(after.constData()), al * sizeof(QChar));
|
||||
uc += al;
|
||||
copystart = copyend + replacements[i].length;
|
||||
i++;
|
||||
}
|
||||
memcpy(static_cast<void *>(uc), static_cast<const void *>(s.constData() + copystart), (s.size() - copystart) * sizeof(QChar));
|
||||
newstring.resize(newlen);
|
||||
s = newstring;
|
||||
caretMode = QRegExp::CaretWontMatch;
|
||||
}
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn QString QRegExp::removeIn(const QString &str)
|
||||
|
||||
Removes every occurrence of this regular expression \a str, and
|
||||
returns the result
|
||||
|
||||
Does the same as replaceIn(str, QString()).
|
||||
|
||||
\sa indexIn(), lastIndexIn(), replaceIn()
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn QString QRegExp::countIn(const QString &str)
|
||||
|
||||
Returns the number of times this regular expression matches
|
||||
in \a str.
|
||||
|
||||
\sa indexIn(), lastIndexIn(), replaceIn()
|
||||
*/
|
||||
|
||||
int QRegExp::countIn(const QString &str) const
|
||||
{
|
||||
QRegExp rx2(*this);
|
||||
int count = 0;
|
||||
int index = -1;
|
||||
int len = str.length();
|
||||
while (index < len - 1) { // count overlapping matches
|
||||
index = rx2.indexIn(str, index + 1);
|
||||
if (index == -1)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
class qt_section_chunk {
|
||||
public:
|
||||
qt_section_chunk() {}
|
||||
qt_section_chunk(int l, QStringRef s) : length(l), string(std::move(s)) {}
|
||||
int length;
|
||||
QStringRef string;
|
||||
};
|
||||
|
||||
static QString extractSections(const QVector<qt_section_chunk> §ions,
|
||||
int start,
|
||||
int end,
|
||||
QString::SectionFlags flags)
|
||||
{
|
||||
const int sectionsSize = sections.size();
|
||||
|
||||
if (!(flags & QString::SectionSkipEmpty)) {
|
||||
if (start < 0)
|
||||
start += sectionsSize;
|
||||
if (end < 0)
|
||||
end += sectionsSize;
|
||||
} else {
|
||||
int skip = 0;
|
||||
for (int k = 0; k < sectionsSize; ++k) {
|
||||
const qt_section_chunk §ion = sections.at(k);
|
||||
if (section.length == section.string.length())
|
||||
skip++;
|
||||
}
|
||||
if (start < 0)
|
||||
start += sectionsSize - skip;
|
||||
if (end < 0)
|
||||
end += sectionsSize - skip;
|
||||
}
|
||||
if (start >= sectionsSize || end < 0 || start > end)
|
||||
return QString();
|
||||
|
||||
QString ret;
|
||||
int x = 0;
|
||||
int first_i = start, last_i = end;
|
||||
for (int i = 0; x <= end && i < sectionsSize; ++i) {
|
||||
const qt_section_chunk §ion = sections.at(i);
|
||||
const bool empty = (section.length == section.string.length());
|
||||
if (x >= start) {
|
||||
if (x == start)
|
||||
first_i = i;
|
||||
if (x == end)
|
||||
last_i = i;
|
||||
if (x != start)
|
||||
ret += section.string;
|
||||
else
|
||||
ret += section.string.mid(section.length);
|
||||
}
|
||||
if (!empty || !(flags & QString::SectionSkipEmpty))
|
||||
x++;
|
||||
}
|
||||
|
||||
if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) {
|
||||
const qt_section_chunk §ion = sections.at(first_i);
|
||||
ret.prepend(section.string.left(section.length));
|
||||
}
|
||||
|
||||
if ((flags & QString::SectionIncludeTrailingSep)
|
||||
&& last_i < sectionsSize - 1) {
|
||||
const qt_section_chunk §ion = sections.at(last_i+1);
|
||||
ret += section.string.left(section.length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*!
|
||||
\a str is treated as a sequence of fields separated by this
|
||||
regular expression.
|
||||
|
||||
\sa splitString()
|
||||
*/
|
||||
QString QRegExp::sectionIn(const QString &str, int start, int end, QString::SectionFlags flags) const
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return str;
|
||||
|
||||
QRegExp sep(*this);
|
||||
sep.setCaseSensitivity((flags & QString::SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive
|
||||
: Qt::CaseSensitive);
|
||||
|
||||
QVector<qt_section_chunk> sections;
|
||||
int n = str.length(), m = 0, last_m = 0, last_len = 0;
|
||||
while ((m = sep.indexIn(str, m)) != -1) {
|
||||
sections.append(qt_section_chunk(last_len, QStringRef(&str, last_m, m - last_m)));
|
||||
last_m = m;
|
||||
last_len = sep.matchedLength();
|
||||
m += qMax(sep.matchedLength(), 1);
|
||||
}
|
||||
sections.append(qt_section_chunk(last_len, QStringRef(&str, last_m, n - last_m)));
|
||||
|
||||
return extractSections(sections, start, end, flags);
|
||||
}
|
||||
|
||||
/*!
|
||||
Splits \a str into substrings wherever this regular expression
|
||||
matches, and returns the list of those strings. If this regular
|
||||
expression does not match anywhere in the string, split() returns a
|
||||
single-element list containing \a str.
|
||||
|
||||
\sa QStringList::join(), section(), QString::split()
|
||||
*/
|
||||
QStringList QRegExp::splitString(const QString &str, Qt::SplitBehavior behavior) const
|
||||
{
|
||||
QRegExp rx2(*this);
|
||||
QStringList list;
|
||||
int start = 0;
|
||||
int extra = 0;
|
||||
int end;
|
||||
while ((end = rx2.indexIn(str, start + extra)) != -1) {
|
||||
int matchedLen = rx2.matchedLength();
|
||||
if (start != end || behavior == Qt::KeepEmptyParts)
|
||||
list.append(str.mid(start, end - start));
|
||||
start = end + matchedLen;
|
||||
extra = (matchedLen == 0) ? 1 : 0;
|
||||
}
|
||||
if (start != str.size() || behavior == Qt::KeepEmptyParts)
|
||||
list.append(str.mid(start, -1));
|
||||
return list;
|
||||
}
|
||||
|
||||
/*!
|
||||
Splits \a str into substrings wherever this regular expression
|
||||
matches, and returns the list of those strings. If this regular
|
||||
expression does not match anywhere in the string, split() returns a
|
||||
single-element list containing \a str.
|
||||
|
||||
\sa QStringList::join(), section(), QString::split()
|
||||
*/
|
||||
QVector<QStringRef> QRegExp::splitStringAsRef(const QString &str, Qt::SplitBehavior behavior) const
|
||||
{
|
||||
QRegExp rx2(*this);
|
||||
QVector<QStringRef> list;
|
||||
int start = 0;
|
||||
int extra = 0;
|
||||
int end;
|
||||
while ((end = rx2.indexIn(str, start + extra)) != -1) {
|
||||
int matchedLen = rx2.matchedLength();
|
||||
if (start != end || behavior == Qt::KeepEmptyParts)
|
||||
list.append(str.midRef(start, end - start));
|
||||
start = end + matchedLen;
|
||||
extra = (matchedLen == 0) ? 1 : 0;
|
||||
}
|
||||
if (start != str.size() || behavior == Qt::KeepEmptyParts)
|
||||
list.append(str.midRef(start, -1));
|
||||
return list;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QStringList QStringList::filter(const QRegExp &rx) const
|
||||
|
||||
\overload
|
||||
|
||||
Returns a list of all the strings that match the regular
|
||||
expression \a rx.
|
||||
*/
|
||||
QStringList QRegExp::filterList(const QStringList &stringList) const
|
||||
{
|
||||
QStringList res;
|
||||
for (const QString &s : stringList) {
|
||||
if (containedIn(s))
|
||||
res << s;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
Replaces every occurrence of the regexp \a rx, in each of the
|
||||
string lists's strings, with \a after. Returns a reference to the
|
||||
string list.
|
||||
*/
|
||||
QStringList QRegExp::replaceIn(const QStringList &stringList, const QString &after) const
|
||||
{
|
||||
QStringList list;
|
||||
for (const QString &s : stringList)
|
||||
list << replaceIn(s, after);
|
||||
return list;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index position of the first exact match of this regexp in
|
||||
\a list, searching forward from index position \a from. Returns
|
||||
-1 if no item matched.
|
||||
|
||||
\sa lastIndexIn(), contains(), exactMatch()
|
||||
*/
|
||||
int QRegExp::indexIn(const QStringList &list, int from)
|
||||
{
|
||||
if (from < 0)
|
||||
from = qMax(from + list.size(), 0);
|
||||
for (int i = from; i < list.size(); ++i) {
|
||||
if (exactMatch(list.at(i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index position of the last exact match of this regexp in
|
||||
\a list, searching backward from index position \a from. If \a
|
||||
from is -1 (the default), the search starts at the last item.
|
||||
Returns -1 if no item matched.
|
||||
|
||||
\sa indexOf(), contains(), QRegExp::exactMatch()
|
||||
*/
|
||||
int QRegExp::lastIndexIn(const QStringList &list, int from)
|
||||
{
|
||||
if (from < 0)
|
||||
from += list.size();
|
||||
else if (from >= list.size())
|
||||
from = list.size() - 1;
|
||||
for (int i = from; i >= 0; --i) {
|
||||
if (exactMatch(list.at(i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_REGEXP_CAPTURE
|
||||
|
||||
/*!
|
||||
@ -4637,6 +5050,7 @@ QString QRegExp::errorString()
|
||||
{
|
||||
return const_cast<const QRegExp *>(this)->errorString();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
@ -108,6 +108,22 @@ public:
|
||||
QString errorString();
|
||||
#endif
|
||||
|
||||
QString replaceIn(const QString &str, const QString &after) const;
|
||||
QString removeIn(const QString &str) const
|
||||
{ return replaceIn(str, QString()); }
|
||||
bool containedIn(const QString &str) const
|
||||
{ return indexIn(str) != -1; }
|
||||
int countIn(const QString &str) const;
|
||||
QString sectionIn(const QString &str, int start, int end, QString::SectionFlags flags) const;
|
||||
|
||||
QStringList splitString(const QString &str, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
|
||||
QVector<QStringRef> splitStringAsRef(const QString &str, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
|
||||
|
||||
int indexIn(const QStringList &list, int from);
|
||||
int lastIndexIn(const QStringList &list, int from);
|
||||
QStringList replaceIn(const QStringList &stringList, const QString &after) const;
|
||||
QStringList filterList(const QStringList &stringList) const;
|
||||
|
||||
static QString escape(const QString &str);
|
||||
|
||||
friend Q_CORE_EXPORT size_t qHash(const QRegExp &key, size_t seed) noexcept;
|
||||
|
@ -3918,138 +3918,7 @@ Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE);
|
||||
*/
|
||||
QString& QString::replace(const QRegExp &rx, const QString &after)
|
||||
{
|
||||
QRegExp rx2(rx);
|
||||
|
||||
if (isEmpty() && rx2.indexIn(*this) == -1)
|
||||
return *this;
|
||||
|
||||
reallocData(uint(d.size) + 1u);
|
||||
|
||||
int index = 0;
|
||||
int numCaptures = rx2.captureCount();
|
||||
int al = after.length();
|
||||
QRegExp::CaretMode caretMode = QRegExp::CaretAtZero;
|
||||
|
||||
if (numCaptures > 0) {
|
||||
const QChar *uc = after.unicode();
|
||||
int numBackRefs = 0;
|
||||
|
||||
for (int i = 0; i < al - 1; i++) {
|
||||
if (uc[i] == QLatin1Char('\\')) {
|
||||
int no = uc[i + 1].digitValue();
|
||||
if (no > 0 && no <= numCaptures)
|
||||
numBackRefs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is the harder case where we have back-references.
|
||||
*/
|
||||
if (numBackRefs > 0) {
|
||||
QVarLengthArray<QStringCapture, 16> captures(numBackRefs);
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < al - 1; i++) {
|
||||
if (uc[i] == QLatin1Char('\\')) {
|
||||
int no = uc[i + 1].digitValue();
|
||||
if (no > 0 && no <= numCaptures) {
|
||||
QStringCapture capture;
|
||||
capture.pos = i;
|
||||
capture.len = 2;
|
||||
|
||||
if (i < al - 2) {
|
||||
int secondDigit = uc[i + 2].digitValue();
|
||||
if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
|
||||
no = (no * 10) + secondDigit;
|
||||
++capture.len;
|
||||
}
|
||||
}
|
||||
|
||||
capture.no = no;
|
||||
captures[j++] = capture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (index <= length()) {
|
||||
index = rx2.indexIn(*this, index, caretMode);
|
||||
if (index == -1)
|
||||
break;
|
||||
|
||||
QString after2(after);
|
||||
for (j = numBackRefs - 1; j >= 0; j--) {
|
||||
const QStringCapture &capture = captures[j];
|
||||
after2.replace(capture.pos, capture.len, rx2.cap(capture.no));
|
||||
}
|
||||
|
||||
replace(index, rx2.matchedLength(), after2);
|
||||
index += after2.length();
|
||||
|
||||
// avoid infinite loop on 0-length matches (e.g., QRegExp("[a-z]*"))
|
||||
if (rx2.matchedLength() == 0)
|
||||
++index;
|
||||
|
||||
caretMode = QRegExp::CaretWontMatch;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is the simple and optimized case where we don't have
|
||||
back-references.
|
||||
*/
|
||||
while (index != -1) {
|
||||
struct {
|
||||
int pos;
|
||||
int length;
|
||||
} replacements[2048];
|
||||
|
||||
int pos = 0;
|
||||
int adjust = 0;
|
||||
while (pos < 2047) {
|
||||
index = rx2.indexIn(*this, index, caretMode);
|
||||
if (index == -1)
|
||||
break;
|
||||
int ml = rx2.matchedLength();
|
||||
replacements[pos].pos = index;
|
||||
replacements[pos++].length = ml;
|
||||
index += ml;
|
||||
adjust += al - ml;
|
||||
// avoid infinite loop
|
||||
if (!ml)
|
||||
index++;
|
||||
}
|
||||
if (!pos)
|
||||
break;
|
||||
replacements[pos].pos = d.size;
|
||||
int newlen = d.size + adjust;
|
||||
|
||||
// to continue searching at the right position after we did
|
||||
// the first round of replacements
|
||||
if (index != -1)
|
||||
index += adjust;
|
||||
QString newstring;
|
||||
newstring.reserve(newlen + 1);
|
||||
QChar *newuc = newstring.data();
|
||||
QChar *uc = newuc;
|
||||
int copystart = 0;
|
||||
int i = 0;
|
||||
while (i < pos) {
|
||||
int copyend = replacements[i].pos;
|
||||
int size = copyend - copystart;
|
||||
memcpy(static_cast<void*>(uc), static_cast<const void *>(d.data() + copystart), size * sizeof(QChar));
|
||||
uc += size;
|
||||
memcpy(static_cast<void *>(uc), static_cast<const void *>(after.d.data()), al * sizeof(QChar));
|
||||
uc += al;
|
||||
copystart = copyend + replacements[i].length;
|
||||
i++;
|
||||
}
|
||||
memcpy(static_cast<void *>(uc), static_cast<const void *>(d.data() + copystart), (d.size - copystart) * sizeof(QChar));
|
||||
newstring.resize(newlen);
|
||||
*this = newstring;
|
||||
caretMode = QRegExp::CaretWontMatch;
|
||||
}
|
||||
*this = rx.replaceIn(*this, after);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@ -4402,17 +4271,7 @@ int QString::lastIndexOf(QRegExp& rx, int from) const
|
||||
*/
|
||||
int QString::count(const QRegExp& rx) const
|
||||
{
|
||||
QRegExp rx2(rx);
|
||||
int count = 0;
|
||||
int index = -1;
|
||||
int len = length();
|
||||
while (index < len - 1) { // count overlapping matches
|
||||
index = rx2.indexIn(*this, index + 1);
|
||||
if (index == -1)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
return rx.countIn(*this);
|
||||
}
|
||||
#endif // QT_NO_REGEXP
|
||||
|
||||
@ -4756,25 +4615,7 @@ static QString extractSections(const QVector<qt_section_chunk> §ions,
|
||||
*/
|
||||
QString QString::section(const QRegExp ®, int start, int end, SectionFlags flags) const
|
||||
{
|
||||
const QChar *uc = unicode();
|
||||
if(!uc)
|
||||
return QString();
|
||||
|
||||
QRegExp sep(reg);
|
||||
sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive
|
||||
: Qt::CaseSensitive);
|
||||
|
||||
QVector<qt_section_chunk> sections;
|
||||
int n = length(), m = 0, last_m = 0, last_len = 0;
|
||||
while ((m = sep.indexIn(*this, m)) != -1) {
|
||||
sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, m - last_m)));
|
||||
last_m = m;
|
||||
last_len = sep.matchedLength();
|
||||
m += qMax(sep.matchedLength(), 1);
|
||||
}
|
||||
sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m)));
|
||||
|
||||
return extractSections(sections, start, end, flags);
|
||||
return reg.sectionIn(*this, start, end, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -7742,28 +7583,6 @@ QVector<QStringRef> QStringRef::split(QChar sep, QString::SplitBehavior behavior
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_REGEXP
|
||||
namespace {
|
||||
template<class ResultList, typename MidMethod>
|
||||
static ResultList splitString(const QString &source, MidMethod mid, const QRegExp &rx, Qt::SplitBehavior behavior)
|
||||
{
|
||||
QRegExp rx2(rx);
|
||||
ResultList list;
|
||||
int start = 0;
|
||||
int extra = 0;
|
||||
int end;
|
||||
while ((end = rx2.indexIn(source, start + extra)) != -1) {
|
||||
int matchedLen = rx2.matchedLength();
|
||||
if (start != end || behavior == Qt::KeepEmptyParts)
|
||||
list.append((source.*mid)(start, end - start));
|
||||
start = end + matchedLen;
|
||||
extra = (matchedLen == 0) ? 1 : 0;
|
||||
}
|
||||
if (start != source.size() || behavior == Qt::KeepEmptyParts)
|
||||
list.append((source.*mid)(start, -1));
|
||||
return list;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/*!
|
||||
\overload
|
||||
\since 5.14
|
||||
@ -7793,7 +7612,7 @@ static ResultList splitString(const QString &source, MidMethod mid, const QRegEx
|
||||
*/
|
||||
QStringList QString::split(const QRegExp &rx, Qt::SplitBehavior behavior) const
|
||||
{
|
||||
return splitString<QStringList>(*this, &QString::mid, rx, behavior);
|
||||
return rx.splitString(*this, behavior);
|
||||
}
|
||||
|
||||
# if QT_DEPRECATED_SINCE(5, 15)
|
||||
@ -7803,7 +7622,7 @@ QStringList QString::split(const QRegExp &rx, Qt::SplitBehavior behavior) const
|
||||
*/
|
||||
QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
|
||||
{
|
||||
return split(rx, mapSplitBehavior(behavior));
|
||||
return rx.splitString(*this, mapSplitBehavior(behavior));
|
||||
}
|
||||
# endif
|
||||
|
||||
@ -7823,7 +7642,7 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
|
||||
*/
|
||||
QVector<QStringRef> QString::splitRef(const QRegExp &rx, Qt::SplitBehavior behavior) const
|
||||
{
|
||||
return splitString<QVector<QStringRef> >(*this, &QString::midRef, rx, behavior);
|
||||
return rx.splitStringAsRef(*this, behavior);
|
||||
}
|
||||
|
||||
# if QT_DEPRECATED_SINCE(5, 15)
|
||||
@ -7834,7 +7653,7 @@ QVector<QStringRef> QString::splitRef(const QRegExp &rx, Qt::SplitBehavior behav
|
||||
*/
|
||||
QVector<QStringRef> QString::splitRef(const QRegExp &rx, SplitBehavior behavior) const
|
||||
{
|
||||
return splitRef(rx, mapSplitBehavior(behavior));
|
||||
return rx.splitStringAsRef(*this, mapSplitBehavior(behavior));
|
||||
}
|
||||
# endif
|
||||
#endif // QT_NO_REGEXP
|
||||
|
@ -460,11 +460,7 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
|
||||
*/
|
||||
QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegExp &rx)
|
||||
{
|
||||
QStringList res;
|
||||
for (int i = 0; i < that->size(); ++i)
|
||||
if (that->at(i).contains(rx))
|
||||
res << that->at(i);
|
||||
return res;
|
||||
return rx.filterList(*that);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -566,8 +562,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QString &b
|
||||
*/
|
||||
void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &rx, const QString &after)
|
||||
{
|
||||
for (int i = 0; i < that->size(); ++i)
|
||||
(*that)[i].replace(rx, after);
|
||||
*that = rx.replaceIn(*that, after);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -716,30 +711,6 @@ QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_REGEXP
|
||||
static int indexOfMutating(const QStringList *that, QRegExp &rx, int from)
|
||||
{
|
||||
if (from < 0)
|
||||
from = qMax(from + that->size(), 0);
|
||||
for (int i = from; i < that->size(); ++i) {
|
||||
if (rx.exactMatch(that->at(i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int lastIndexOfMutating(const QStringList *that, QRegExp &rx, int from)
|
||||
{
|
||||
if (from < 0)
|
||||
from += that->size();
|
||||
else if (from >= that->size())
|
||||
from = that->size() - 1;
|
||||
for (int i = from; i >= 0; --i) {
|
||||
if (rx.exactMatch(that->at(i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int QStringList::indexOf(const QRegExp &rx, int from) const
|
||||
|
||||
@ -752,7 +723,7 @@ static int lastIndexOfMutating(const QStringList *that, QRegExp &rx, int from)
|
||||
int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegExp &rx, int from)
|
||||
{
|
||||
QRegExp rx2(rx);
|
||||
return indexOfMutating(that, rx2, from);
|
||||
return rx2.indexIn(*that, from);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -771,7 +742,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegExp &rx, i
|
||||
*/
|
||||
int QtPrivate::QStringList_indexOf(const QStringList *that, QRegExp &rx, int from)
|
||||
{
|
||||
return indexOfMutating(that, rx, from);
|
||||
return rx.indexIn(*that, from);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -787,7 +758,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, QRegExp &rx, int fro
|
||||
int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegExp &rx, int from)
|
||||
{
|
||||
QRegExp rx2(rx);
|
||||
return lastIndexOfMutating(that, rx2, from);
|
||||
return rx2.lastIndexIn(*that, from);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -807,7 +778,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegExp &r
|
||||
*/
|
||||
int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from)
|
||||
{
|
||||
return lastIndexOfMutating(that, rx, from);
|
||||
return rx.lastIndexIn(*that, from);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -69,6 +69,20 @@ private slots:
|
||||
void validityCheck_data();
|
||||
void validityCheck();
|
||||
void escapeSequences();
|
||||
|
||||
void splitString_data();
|
||||
void splitString();
|
||||
|
||||
void countIn();
|
||||
void containedIn();
|
||||
|
||||
void replaceIn_data();
|
||||
void replaceIn();
|
||||
void removeIn_data();
|
||||
void removeIn();
|
||||
|
||||
void filterList();
|
||||
void replaceInList();
|
||||
};
|
||||
|
||||
// Testing get/set functions
|
||||
@ -1381,6 +1395,155 @@ void tst_QRegExp::escapeSequences()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QRegExp::splitString_data()
|
||||
{
|
||||
QTest::addColumn<QString>("string");
|
||||
QTest::addColumn<QString>("pattern");
|
||||
QTest::addColumn<QStringList>("result");
|
||||
|
||||
QTest::newRow("data01") << "Some text\n\twith strange whitespace."
|
||||
<< "\\s+"
|
||||
<< (QStringList() << "Some" << "text" << "with" << "strange" << "whitespace." );
|
||||
|
||||
QTest::newRow("data02") << "This time, a normal English sentence."
|
||||
<< "\\W+"
|
||||
<< (QStringList() << "This" << "time" << "a" << "normal" << "English" << "sentence" << "");
|
||||
|
||||
QTest::newRow("data03") << "Now: this sentence fragment."
|
||||
<< "\\b"
|
||||
<< (QStringList() << "" << "Now" << ": " << "this" << " " << "sentence" << " " << "fragment" << ".");
|
||||
}
|
||||
|
||||
void tst_QRegExp::splitString()
|
||||
{
|
||||
QFETCH(QString, string);
|
||||
QFETCH(QString, pattern);
|
||||
QFETCH(QStringList, result);
|
||||
QStringList list = QRegExp(pattern).splitString(string);
|
||||
QVERIFY(list == result);
|
||||
|
||||
QVERIFY(list == result);
|
||||
|
||||
result.removeAll(QString());
|
||||
|
||||
list = QRegExp(pattern).splitString(string, Qt::SkipEmptyParts);
|
||||
QVERIFY(list == result);
|
||||
}
|
||||
|
||||
void tst_QRegExp::countIn()
|
||||
{
|
||||
QString a;
|
||||
a="ABCDEFGHIEfGEFG"; // 15 chars
|
||||
QCOMPARE(QRegExp("[FG][HI]").countIn(a),1);
|
||||
QCOMPARE(QRegExp("[G][HE]").countIn(a),2);
|
||||
}
|
||||
|
||||
|
||||
void tst_QRegExp::containedIn()
|
||||
{
|
||||
QString a;
|
||||
a="ABCDEFGHIEfGEFG"; // 15 chars
|
||||
QVERIFY(QRegExp("[FG][HI]").containedIn(a));
|
||||
QVERIFY(QRegExp("[G][HE]").containedIn(a));
|
||||
}
|
||||
|
||||
void tst_QRegExp::replaceIn_data()
|
||||
{
|
||||
QTest::addColumn<QString>("string" );
|
||||
QTest::addColumn<QString>("regexp" );
|
||||
QTest::addColumn<QString>("after" );
|
||||
QTest::addColumn<QString>("result" );
|
||||
|
||||
QTest::newRow( "rem00" ) << QString("alpha") << QString("a+") << QString("") << QString("lph");
|
||||
QTest::newRow( "rem01" ) << QString("banana") << QString("^.a") << QString("") << QString("nana");
|
||||
QTest::newRow( "rem02" ) << QString("") << QString("^.a") << QString("") << QString("");
|
||||
QTest::newRow( "rem03" ) << QString("") << QString("^.a") << QString() << QString("");
|
||||
QTest::newRow( "rem04" ) << QString() << QString("^.a") << QString("") << QString();
|
||||
QTest::newRow( "rem05" ) << QString() << QString("^.a") << QString() << QString();
|
||||
|
||||
QTest::newRow( "rep00" ) << QString("A <i>bon mot</i>.") << QString("<i>([^<]*)</i>") << QString("\\emph{\\1}") << QString("A \\emph{bon mot}.");
|
||||
QTest::newRow( "rep01" ) << QString("banana") << QString("^.a()") << QString("\\1") << QString("nana");
|
||||
QTest::newRow( "rep02" ) << QString("banana") << QString("(ba)") << QString("\\1X\\1") << QString("baXbanana");
|
||||
QTest::newRow( "rep03" ) << QString("banana") << QString("(ba)(na)na") << QString("\\2X\\1") << QString("naXba");
|
||||
|
||||
QTest::newRow("backref00") << QString("\\1\\2\\3\\4\\5\\6\\7\\8\\9\\A\\10\\11") << QString("\\\\[34]")
|
||||
<< QString("X") << QString("\\1\\2XX\\5\\6\\7\\8\\9\\A\\10\\11");
|
||||
QTest::newRow("backref01") << QString("foo") << QString("[fo]") << QString("\\1") << QString("\\1\\1\\1");
|
||||
QTest::newRow("backref02") << QString("foo") << QString("([fo])") << QString("(\\1)") << QString("(f)(o)(o)");
|
||||
QTest::newRow("backref03") << QString("foo") << QString("([fo])") << QString("\\2") << QString("\\2\\2\\2");
|
||||
QTest::newRow("backref04") << QString("foo") << QString("([fo])") << QString("\\10") << QString("f0o0o0");
|
||||
QTest::newRow("backref05") << QString("foo") << QString("([fo])") << QString("\\11") << QString("f1o1o1");
|
||||
QTest::newRow("backref06") << QString("foo") << QString("([fo])") << QString("\\19") << QString("f9o9o9");
|
||||
QTest::newRow("backref07") << QString("foo") << QString("(f)(o+)")
|
||||
<< QString("\\2\\1\\10\\20\\11\\22\\19\\29\\3")
|
||||
<< QString("ooff0oo0f1oo2f9oo9\\3");
|
||||
QTest::newRow("backref08") << QString("abc") << QString("(((((((((((((([abc]))))))))))))))")
|
||||
<< QString("{\\14}") << QString("{a}{b}{c}");
|
||||
QTest::newRow("backref09") << QString("abcdefghijklmn")
|
||||
<< QString("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)")
|
||||
<< QString("\\19\\18\\17\\16\\15\\14\\13\\12\\11\\10"
|
||||
"\\9\\90\\8\\80\\7\\70\\6\\60\\5\\50\\4\\40\\3\\30\\2\\20\\1")
|
||||
<< QString("a9a8a7a6a5nmlkjii0hh0gg0ff0ee0dd0cc0bb0a");
|
||||
QTest::newRow("backref10") << QString("abc") << QString("((((((((((((((abc))))))))))))))")
|
||||
<< QString("\\0\\01\\011") << QString("\\0\\01\\011");
|
||||
QTest::newRow("invalid") << QString("") << QString("invalid regex\\") << QString("") << QString("");
|
||||
}
|
||||
|
||||
void tst_QRegExp::replaceIn()
|
||||
{
|
||||
QFETCH( QString, string );
|
||||
QFETCH( QString, regexp );
|
||||
QFETCH( QString, after );
|
||||
|
||||
QString s2 = string;
|
||||
s2 = QRegExp(regexp).replaceIn(s2, after);
|
||||
QTEST( s2, "result" );
|
||||
s2 = string;
|
||||
}
|
||||
|
||||
void tst_QRegExp::removeIn_data()
|
||||
{
|
||||
replaceIn_data();
|
||||
}
|
||||
|
||||
void tst_QRegExp::removeIn()
|
||||
{
|
||||
QFETCH( QString, string );
|
||||
QFETCH( QString, regexp );
|
||||
QFETCH( QString, after );
|
||||
|
||||
if ( after.length() == 0 ) {
|
||||
QString s2 = string;
|
||||
s2 = QRegExp(regexp).removeIn(s2);
|
||||
QTEST( s2, "result" );
|
||||
} else {
|
||||
QCOMPARE( 0, 0 ); // shut Qt Test
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QRegExp::filterList()
|
||||
{
|
||||
QStringList list3, list4;
|
||||
list3 << "Bill Gates" << "Joe Blow" << "Bill Clinton";
|
||||
list3 = QRegExp("[i]ll") .filterList(list3);
|
||||
list4 << "Bill Gates" << "Bill Clinton";
|
||||
QCOMPARE( list3, list4 );
|
||||
}
|
||||
|
||||
void tst_QRegExp::replaceInList()
|
||||
{
|
||||
QStringList list3, list4;
|
||||
list3 << "alpha" << "beta" << "gamma" << "epsilon";
|
||||
list3 = QRegExp("^a").replaceIn(list3, "o");
|
||||
list4 << "olpha" << "beta" << "gamma" << "epsilon";
|
||||
QCOMPARE( list3, list4 );
|
||||
|
||||
QStringList list5, list6;
|
||||
list5 << "Bill Clinton" << "Gates, Bill";
|
||||
list6 << "Bill Clinton" << "Bill Gates";
|
||||
list5 = QRegExp("^(.*), (.*)$").replaceIn(list5, "\\2 \\1");
|
||||
QCOMPARE( list5, list6 );
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QRegExp)
|
||||
#include "tst_qregexp.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user