QRegularExpression: support for QString overloads
authorGiuseppe D'Angelo <dangelog@gmail.com>
Sun, 12 Feb 2012 01:04:16 +0000 (01:04 +0000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 14 Mar 2012 23:37:56 +0000 (00:37 +0100)
Added support for QString overloads taking a QRegularExpression.

Change-Id: I8608ab0b66e5fdd2e966992e1072cf1ef7883c8e
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
doc/src/snippets/qstring/main.cpp
src/corelib/tools/qstring.cpp
src/corelib/tools/qstring.h
tests/auto/corelib/tools/qstring/tst_qstring.cpp

index d0a4457..d7299e8 100644 (file)
@@ -314,6 +314,11 @@ void Widget::countFunction()
     QString str = "banana and panama";
     str.count(QRegExp("a[nm]a"));    // returns 4
     //! [18]
+
+    //! [95]
+    QString str = "banana and panama";
+    str.count(QRegularExpression("a[nm]a"));    // returns 4
+    //! [95]
 }
 
 void Widget::dataFunction()
@@ -384,6 +389,11 @@ void Widget::firstIndexOfFunction()
     QString str = "the minimum";
     str.indexOf(QRegExp("m[aeiou]"), 0);       // returns 4
     //! [25]
+
+    //! [93]
+    QString str = "the minimum";
+    str.indexOf(QRegularExpression("m[aeiou]"), 0);       // returns 4
+    //! [93]
 }
 
 void Widget::insertFunction()
@@ -429,6 +439,11 @@ void Widget::lastIndexOfFunction()
     QString str = "the minimum";
     str.lastIndexOf(QRegExp("m[aeiou]"));      // returns 8
     //! [30]
+
+    //! [94]
+    QString str = "the minimum";
+    str.lastIndexOf(QRegularExpression("m[aeiou]"));      // returns 8
+    //! [94]
 }
 
 void Widget::leftFunction()
@@ -499,6 +514,12 @@ void Widget::removeFunction()
     r.remove(QRegExp("[aeiou]."));
     // r == "The"
     //! [39]
+
+    //! [96]
+    QString r = "Telephone";
+    r.remove(QRegularExpression("[aeiou]."));
+    // r == "The"
+    //! [96]
 }
 
 void Widget::replaceFunction()
@@ -533,6 +554,18 @@ void Widget::replaceFunction()
     equis.replace("xx", "x");
     // equis == "xxx"    
     //! [86]
+
+    //! [87]
+    QString s = "Banana";
+    s.replace(QRegularExpression("a[mn]"), "ox");
+    // s == "Boxoxa"
+    //! [87]
+
+    //! [88]
+    QString t = "A <i>bon mot</i>.";
+    t.replace(QRegularExpression("<i>([^<]*)</i>"), "\\emph{\\1}");
+    // t == "A \\emph{bon mot}."
+    //! [88]
 }
 
 void Widget::reserveFunction()
@@ -627,9 +660,16 @@ void Widget::sectionFunction()
     //! [55]
     QString line = "forename\tmiddlename  surname \t \t phone";
     QRegExp sep("\\s+");
-    str = line.section(sep, 2, 2); // s == "surname"
-    str = line.section(sep, -3, -2); // s == "middlename  surname"
+    str = line.section(sep, 2, 2); // str == "surname"
+    str = line.section(sep, -3, -2); // str == "middlename  surname"
     //! [55]
+
+    //! [89]
+    QString line = "forename\tmiddlename  surname \t \t phone";
+    QRegularExpression sep("\\s+");
+    str = line.section(sep, 2, 2); // str == "surname"
+    str = line.section(sep, -3, -2); // str == "middlename  surname"
+    //! [89]
 }
 
 void Widget::setNumFunction()
@@ -682,6 +722,27 @@ void Widget::splitFunction()
     list = str.split(QRegExp("\\b"));
     // list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
     //! [61]
+
+    //! [90]
+    QString str;
+    QStringList list;
+
+    str = "Some  text\n\twith  strange whitespace.";
+    list = str.split(QRegularExpression("\\s+"));
+    // list: [ "Some", "text", "with", "strange", "whitespace." ]
+    //! [90]
+
+    //! [91]
+    str = "This time, a normal English sentence.";
+    list = str.split(QRegularExpression("\\W+"), QString::SkipEmptyParts);
+    // list: [ "This", "time", "a", "normal", "English", "sentence" ]
+    //! [91]
+
+    //! [92]
+    str = "Now: this sentence fragment.";
+    list = str.split(QRegularExpression("\\b"));
+    // list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
+    //! [92]
 }
 
 void Widget::splitCaseSensitiveFunction()
index 584502f..878403f 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "qstringlist.h"
 #include "qregexp.h"
+#include "qregularexpression.h"
 #include "qunicodetables_p.h"
 #ifndef QT_NO_TEXTCODEC
 #include <qtextcodec.h>
@@ -1741,6 +1742,18 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
 */
 
 /*!
+  \fn QString &QString::remove(const QRegularExpression &re)
+  \since 5.0
+
+  Removes every occurrence of the regular expression \a re in the
+  string, and returns a reference to the string. For example:
+
+  \snippet doc/src/snippets/qstring/main.cpp 96
+
+  \sa indexOf(), lastIndexOf(), replace()
+*/
+
+/*!
   \fn QString &QString::replace(int position, int n, const QString &after)
 
   Replaces \a n characters beginning at index \a position with
@@ -2923,6 +2936,138 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
 }
 #endif
 
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+  \overload replace()
+  \since 5.0
+
+  Replaces every occurrence of the regular expression \a re in the
+  string with \a after. Returns a reference to the string. For
+  example:
+
+  \snippet doc/src/snippets/qstring/main.cpp 87
+
+  For regular expressions containing capturing groups,
+  occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are replaced
+  with the string captured by the corresponding capturing group.
+
+  \snippet doc/src/snippets/qstring/main.cpp 88
+
+  \sa indexOf(), lastIndexOf(), remove(), QRegularExpression, QRegularExpressionMatch
+*/
+QString &QString::replace(const QRegularExpression &re, const QString &after)
+{
+    if (!re.isValid()) {
+        qWarning("QString::replace: invalid QRegularExpresssion object");
+        return *this;
+    }
+
+    const QString copy(*this);
+    QRegularExpressionMatchIterator iterator = re.globalMatch(copy);
+    if (!iterator.hasNext()) // no matches at all
+        return *this;
+
+    realloc();
+
+    int numCaptures = re.captureCount();
+
+    // 1. build the backreferences vector, holding where the backreferences
+    // are in the replacement string
+    QVector<QStringCapture> backReferences;
+    const int al = after.length();
+    const QChar *ac = after.unicode();
+
+    for (int i = 0; i < al - 1; i++) {
+        if (ac[i] == QLatin1Char('\\')) {
+            int no = ac[i + 1].digitValue();
+            if (no > 0 && no <= numCaptures) {
+                QStringCapture backReference;
+                backReference.pos = i;
+                backReference.len = 2;
+
+                if (i < al - 2) {
+                    int secondDigit = ac[i + 2].digitValue();
+                    if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
+                        no = (no * 10) + secondDigit;
+                        ++backReference.len;
+                    }
+                }
+
+                backReference.no = no;
+                backReferences.append(backReference);
+            }
+        }
+    }
+
+    // 2. iterate on the matches. For every match, copy in chunks
+    // - the part before the match
+    // - the after string, with the proper replacements for the backreferences
+
+    int newLength = 0; // length of the new string, with all the replacements
+    int lastEnd = 0;
+    QVector<QStringRef> chunks;
+    while (iterator.hasNext()) {
+        QRegularExpressionMatch match = iterator.next();
+        int len;
+        // add the part before the match
+        len = match.capturedStart() - lastEnd;
+        if (len > 0) {
+            chunks << copy.midRef(lastEnd, len);
+            newLength += len;
+        }
+
+        lastEnd = 0;
+        // add the after string, with replacements for the backreferences
+        foreach (const QStringCapture &backReference, backReferences) {
+            // part of "after" before the backreference
+            len = backReference.pos - lastEnd;
+            if (len > 0) {
+                chunks << after.midRef(lastEnd, len);
+                newLength += len;
+            }
+
+            // backreference itself
+            len = match.capturedLength(backReference.no);
+            if (len > 0) {
+                chunks << copy.midRef(match.capturedStart(backReference.no), len);
+                newLength += len;
+            }
+
+            lastEnd = backReference.pos + backReference.len;
+        }
+
+        // add the last part of the after string
+        len = after.length() - lastEnd;
+        if (len > 0) {
+            chunks << after.midRef(lastEnd, len);
+            newLength += len;
+        }
+
+        lastEnd = match.capturedEnd();
+    }
+
+    // 3. trailing string after the last match
+    if (copy.length() > lastEnd) {
+        chunks << copy.midRef(lastEnd);
+        newLength += copy.length() - lastEnd;
+    }
+
+    // 4. assemble the chunks together
+    resize(newLength);
+    int i = 0;
+    QChar *uc = data();
+    foreach (const QStringRef &chunk, chunks) {
+        int len = chunk.length();
+        memcpy(uc + i, chunk.unicode(), len * sizeof(QChar));
+        i += len;
+    }
+
+    return *this;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
 /*!
     Returns the number of (potentially overlapping) occurrences of
     the string \a str in this string.
@@ -3122,6 +3267,118 @@ int QString::count(const QRegExp& rx) const
 }
 #endif // QT_NO_REGEXP
 
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+    \overload indexOf()
+    \since 5.0
+
+    Returns the index position of the first match of the regular
+    expression \a re in the string, searching forward from index
+    position \a from. Returns -1 if \a re didn't match anywhere.
+
+    Example:
+
+    \snippet doc/src/snippets/qstring/main.cpp 93
+*/
+int QString::indexOf(const QRegularExpression& re, int from) const
+{
+    if (!re.isValid()) {
+        qWarning("QString::indexOf: invalid QRegularExpresssion object");
+        return -1;
+    }
+
+    QRegularExpressionMatch match = re.match(*this, from);
+    if (match.hasMatch())
+        return match.capturedStart();
+
+    return -1;
+}
+
+/*!
+    \overload lastIndexOf()
+    \since 5.0
+
+    Returns the index position of the last match of the regular
+    expression \a re in the string, which starts before the index
+    position \a from. Returns -1 if \a re didn't match anywhere.
+
+    Example:
+
+    \snippet doc/src/snippets/qstring/main.cpp 94
+*/
+int QString::lastIndexOf(const QRegularExpression &re, int from) const
+{
+    if (!re.isValid()) {
+        qWarning("QString::lastIndexOf: invalid QRegularExpresssion object");
+        return -1;
+    }
+
+    int endpos = (from < 0) ? (size() + from + 1) : (from + 1);
+
+    QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
+    int lastIndex = -1;
+    while (iterator.hasNext()) {
+        QRegularExpressionMatch match = iterator.next();
+        int start = match.capturedStart();
+        if (start < endpos)
+            lastIndex = start;
+        else
+            break;
+    }
+
+    return lastIndex;
+}
+
+/*! \overload contains()
+    \since 5.0
+
+    Returns true if the regular expression \a re matches somewhere in
+    this string; otherwise returns false.
+*/
+bool QString::contains(const QRegularExpression &re) const
+{
+    if (!re.isValid()) {
+        qWarning("QString::contains: invalid QRegularExpresssion object");
+        return false;
+    }
+    QRegularExpressionMatch match = re.match(*this);
+    return match.hasMatch();
+}
+
+/*!
+    \overload count()
+    \since 5.0
+
+    Returns the number of times the regular expression \a re matches
+    in the string.
+
+    This function counts overlapping matches, so in the example
+    below, there are four instances of "ana" or "ama":
+
+    \snippet doc/src/snippets/qstring/main.cpp 95
+*/
+int QString::count(const QRegularExpression &re) const
+{
+    if (!re.isValid()) {
+        qWarning("QString::count: invalid QRegularExpresssion object");
+        return 0;
+    }
+    int count = 0;
+    int index = -1;
+    int len = length();
+    while (index < len - 1) {
+        QRegularExpressionMatch match = re.match(*this, index + 1);
+        if (!match.hasMatch())
+            break;
+        index = match.capturedStart();
+        count++;
+    }
+    return count;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
 /*! \fn int QString::count() const
 
     \overload count()
@@ -3249,6 +3506,49 @@ public:
     QString string;
 };
 
+static QString extractSections(const QList<qt_section_chunk> &sections,
+                               int start,
+                               int end,
+                               QString::SectionFlags flags)
+{
+    if (start < 0)
+        start += sections.count();
+    if (end < 0)
+        end += sections.count();
+
+    QString ret;
+    int x = 0;
+    int first_i = start, last_i = end;
+    for (int i = 0; x <= end && i < sections.size(); ++i) {
+        const qt_section_chunk &section = 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 < sections.size()) {
+        const qt_section_chunk &section = sections.at(first_i);
+        ret.prepend(section.string.left(section.length));
+    }
+
+    if ((flags & QString::SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
+        const qt_section_chunk &section = sections.at(last_i+1);
+        ret += section.string.left(section.length);
+    }
+
+    return ret;
+}
+
 /*!
     \overload section()
 
@@ -3282,41 +3582,57 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
     }
     sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
 
-    if(start < 0)
-        start += sections.count();
-    if(end < 0)
-        end += sections.count();
+    return extractSections(sections, start, end, flags);
+}
+#endif
 
-    QString ret;
-    int x = 0;
-    int first_i = start, last_i = end;
-    for (int i = 0; x <= end && i < sections.size(); ++i) {
-        const qt_section_chunk &section = 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 & SectionSkipEmpty))
-            x++;
-    }
-    if((flags & SectionIncludeLeadingSep) && first_i < sections.size()) {
-        const qt_section_chunk &section = sections.at(first_i);
-        ret.prepend(section.string.left(section.length));
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+    \overload section()
+    \since 5.0
+
+    This string is treated as a sequence of fields separated by the
+    regular expression, \a re.
+
+    \snippet doc/src/snippets/qstring/main.cpp 89
+
+    \warning Using this QRegularExpression version is much more expensive than
+    the overloaded string and character versions.
+
+    \sa split() simplified()
+*/
+QString QString::section(const QRegularExpression &re, int start, int end, SectionFlags flags) const
+{
+    if (!re.isValid()) {
+        qWarning("QString::section: invalid QRegularExpression object");
+        return QString();
     }
-    if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
-        const qt_section_chunk &section = sections.at(last_i+1);
-        ret += section.string.left(section.length);
+
+    const QChar *uc = unicode();
+    if (!uc)
+        return QString();
+
+    QRegularExpression sep(re);
+    if (flags & SectionCaseInsensitiveSeps)
+        sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption);
+
+    QList<qt_section_chunk> sections;
+    int n = length(), m = 0, last_m = 0, last_len = 0;
+    QRegularExpressionMatchIterator iterator = sep.globalMatch(*this);
+    while (iterator.hasNext()) {
+        QRegularExpressionMatch match = iterator.next();
+        m = match.capturedStart();
+        sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
+        last_m = m;
+        last_len = match.capturedLength();
     }
-    return ret;
+    sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
+
+    return extractSections(sections, start, end, flags);
 }
-#endif
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
 
 /*!
     Returns a substring that contains the \a n leftmost characters
@@ -6077,6 +6393,62 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
 }
 #endif
 
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+    \overload
+    \since 5.0
+
+    Splits the string into substrings wherever the regular expression
+    \a re matches, and returns the list of those strings. If \a re
+    does not match anywhere in the string, split() returns a
+    single-element list containing this string.
+
+    Here's an example where we extract the words in a sentence
+    using one or more whitespace characters as the separator:
+
+    \snippet doc/src/snippets/qstring/main.cpp 90
+
+    Here's a similar example, but this time we use any sequence of
+    non-word characters as the separator:
+
+    \snippet doc/src/snippets/qstring/main.cpp 91
+
+    Here's a third example where we use a zero-length assertion,
+    \bold{\\b} (word boundary), to split the string into an
+    alternating sequence of non-word and word tokens:
+
+    \snippet doc/src/snippets/qstring/main.cpp 92
+
+    \sa QStringList::join(), section()
+*/
+QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior) const
+{
+    QStringList list;
+    if (!re.isValid()) {
+        qWarning("QString::split: invalid QRegularExpression object");
+        return list;
+    }
+
+    int start = 0;
+    int end = 0;
+    QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
+    while (iterator.hasNext()) {
+        QRegularExpressionMatch match = iterator.next();
+        end = match.capturedStart();
+        if (start != end || behavior == KeepEmptyParts)
+            list.append(mid(start, end - start));
+        start = match.capturedEnd();
+    }
+
+    if (start != size() || behavior == KeepEmptyParts)
+        list.append(mid(start));
+
+    return list;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
 /*!
     \enum QString::NormalizationForm
 
index b71484f..de5cd2c 100644 (file)
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
 
 class QCharRef;
 class QRegExp;
+class QRegularExpression;
 class QStringList;
 class QTextCodec;
 class QLatin1String;
@@ -283,6 +284,13 @@ public:
     inline bool contains(QRegExp &rx) const { return indexOf(rx) != -1; }
 #endif
 
+#ifndef QT_NO_REGEXP
+    int indexOf(const QRegularExpression &re, int from = 0) const;
+    int lastIndexOf(const QRegularExpression &re, int from = -1) const;
+    bool contains(const QRegularExpression &re) const;
+    int count(const QRegularExpression &re) const;
+#endif
+
     enum SectionFlag {
         SectionDefault             = 0x00,
         SectionSkipEmpty           = 0x01,
@@ -297,7 +305,9 @@ public:
 #ifndef QT_NO_REGEXP
     QString section(const QRegExp &reg, int start, int end = -1, SectionFlags flags = SectionDefault) const;
 #endif
-
+#ifndef QT_NO_REGEXP
+    QString section(const QRegularExpression &re, int start, int end = -1, SectionFlags flags = SectionDefault) const;
+#endif
     QString left(int n) const Q_REQUIRED_RESULT;
     QString right(int n) const Q_REQUIRED_RESULT;
     QString mid(int position, int n = -1) const Q_REQUIRED_RESULT;
@@ -370,6 +380,11 @@ public:
     inline QString &remove(const QRegExp &rx)
     { return replace(rx, QString()); }
 #endif
+#ifndef QT_NO_REGEXP
+    QString &replace(const QRegularExpression &re, const QString  &after);
+    inline QString &remove(const QRegularExpression &re)
+    { return replace(re, QString()); }
+#endif
 
     enum SplitBehavior { KeepEmptyParts, SkipEmptyParts };
 
@@ -380,7 +395,9 @@ public:
 #ifndef QT_NO_REGEXP
     QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
 #endif
-
+#ifndef QT_NO_REGEXP
+    QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
+#endif
     enum NormalizationForm {
         NormalizationForm_D,
         NormalizationForm_C,
index 355e4d7..7d4a9b5 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <QtTest/QtTest>
 #include <qregexp.h>
+#include <qregularexpression.h>
 #include <qtextcodec.h>
 #include <qtextstream.h>
 #include <qstringlist.h>
@@ -194,6 +195,7 @@ private slots:
     void localeAwareCompare();
     void split_data();
     void split();
+    void split_regexp_data();
     void split_regexp();
     void fromUtf16_data();
     void fromUtf16();
@@ -1080,6 +1082,17 @@ void tst_QString::indexOf()
         QCOMPARE( rx2.matchedLength(), -1 );
     }
 
+    {
+        QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
+        if (!bcs)
+            options |= QRegularExpression::CaseInsensitiveOption;
+
+        QRegularExpression re(QRegularExpression::escape(needle), options);
+        QEXPECT_FAIL("data58", "QRegularExpression does not support case folding", Continue);
+        QEXPECT_FAIL("data59", "QRegularExpression does not support case folding", Continue);
+        QCOMPARE( haystack.indexOf(re, startpos), resultpos );
+    }
+
     if (cs == Qt::CaseSensitive) {
         QCOMPARE( haystack.indexOf(needle, startpos), resultpos );
         QCOMPARE( haystack.indexOf(ref, startpos), resultpos );
@@ -1267,6 +1280,15 @@ void tst_QString::lastIndexOf()
             QCOMPARE(rx1.matchedLength(), -1);
             QCOMPARE(rx2.matchedLength(), -1);
         }
+
+        {
+            QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
+            if (!caseSensitive)
+                options |= QRegularExpression::CaseInsensitiveOption;
+
+            QRegularExpression re(QRegularExpression::escape(needle), options);
+            QCOMPARE(haystack.lastIndexOf(re, from), expected);
+        }
     }
 
     if (cs == Qt::CaseSensitive) {
@@ -1302,6 +1324,9 @@ void tst_QString::count()
     QCOMPARE(a.count( "", Qt::CaseInsensitive), 16);
     QCOMPARE(a.count(QRegExp("[FG][HI]")),1);
     QCOMPARE(a.count(QRegExp("[G][HE]")),2);
+    QCOMPARE(a.count(QRegularExpression("[FG][HI]")), 1);
+    QCOMPARE(a.count(QRegularExpression("[G][HE]")), 2);
+
 
     CREATE_REF(QLatin1String("FG"));
     QCOMPARE(a.count(ref),2);
@@ -1327,6 +1352,8 @@ void tst_QString::contains()
     QVERIFY(a.contains( "", Qt::CaseInsensitive));
     QVERIFY(a.contains(QRegExp("[FG][HI]")));
     QVERIFY(a.contains(QRegExp("[G][HE]")));
+    QVERIFY(a.contains(QRegularExpression("[FG][HI]")));
+    QVERIFY(a.contains(QRegularExpression("[G][HE]")));
 
     CREATE_REF(QLatin1String("FG"));
     QVERIFY(a.contains(ref));
@@ -2172,6 +2199,9 @@ void tst_QString::replace_regexp()
     QString s2 = string;
     s2.replace( QRegExp(regexp), after );
     QTEST( s2, "result" );
+    s2 = string;
+    s2.replace( QRegularExpression(regexp), after );
+    QTEST( s2, "result" );
 }
 
 void tst_QString::remove_uint_uint()
@@ -2236,8 +2266,13 @@ void tst_QString::remove_regexp()
     QFETCH( QString, after );
 
     if ( after.length() == 0 ) {
-        string.remove( QRegExp(regexp) );
-        QTEST( string, "result" );
+        QString s2 = string;
+        s2.remove( QRegExp(regexp) );
+        QTEST( s2, "result" );
+
+        s2 = string;
+        s2.remove( QRegularExpression(regexp) );
+        QTEST( s2, "result" );
     } else {
         QCOMPARE( 0, 0 ); // shut QtTest
     }
@@ -3978,8 +4013,12 @@ void tst_QString::section()
     QFETCH( bool, regexp );
     if (regexp) {
         QCOMPARE( wholeString.section( QRegExp(sep), start, end, QString::SectionFlag(flags) ), sectionString );
+        QCOMPARE( wholeString.section( QRegularExpression(sep), start, end, QString::SectionFlag(flags) ), sectionString );
     } else {
         QCOMPARE( wholeString.section( sep, start, end, QString::SectionFlag(flags) ), sectionString );
+        QCOMPARE( wholeString.section( QRegExp(QRegExp::escape(sep)), start, end, QString::SectionFlag(flags) ), sectionString );
+        QCOMPARE( wholeString.section( QRegularExpression(QRegularExpression::escape(sep)), start, end, QString::SectionFlag(flags) ), sectionString );
+
     }
 }
 
@@ -4500,6 +4539,7 @@ void tst_QString::split()
     QFETCH(QStringList, result);
 
     QRegExp rx = QRegExp(QRegExp::escape(sep));
+    QRegularExpression re(QRegularExpression::escape(sep));
 
     QStringList list;
 
@@ -4507,6 +4547,8 @@ void tst_QString::split()
     QVERIFY(list == result);
     list = str.split(rx);
     QVERIFY(list == result);
+    list = str.split(re);
+    QVERIFY(list == result);
     if (sep.size() == 1) {
         list = str.split(sep.at(0));
         QVERIFY(list == result);
@@ -4516,6 +4558,8 @@ void tst_QString::split()
     QVERIFY(list == result);
     list = str.split(rx, QString::KeepEmptyParts);
     QVERIFY(list == result);
+    list = str.split(re, QString::KeepEmptyParts);
+    QVERIFY(list == result);
     if (sep.size() == 1) {
         list = str.split(sep.at(0), QString::KeepEmptyParts);
         QVERIFY(list == result);
@@ -4526,39 +4570,51 @@ void tst_QString::split()
     QVERIFY(list == result);
     list = str.split(rx, QString::SkipEmptyParts);
     QVERIFY(list == result);
+    list = str.split(re, QString::SkipEmptyParts);
+    QVERIFY(list == result);
     if (sep.size() == 1) {
         list = str.split(sep.at(0), QString::SkipEmptyParts);
         QVERIFY(list == result);
     }
 }
 
+void tst_QString::split_regexp_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_QString::split_regexp()
 {
-    QString str1 = "Some  text\n\twith  strange whitespace.";
-    QStringList list1 = str1.split(QRegExp("\\s+"));
-    QStringList result1;
-    result1 << "Some" << "text" << "with" << "strange" << "whitespace.";
-    QVERIFY(list1 == result1);
-    list1 = str1.split(QRegExp("\\s"), QString::SkipEmptyParts);
-    QVERIFY(list1 == result1);
-
-    QString str2 = "This time, a normal English sentence.";
-    QStringList list2 = str2.split(QRegExp("\\W+"));
-    QStringList result2;
-    result2 << "This" << "time" << "a" << "normal" << "English" << "sentence" << "";
-    QVERIFY(list2 == result2);
-    list2 = str2.split(QRegExp("\\W"), QString::SkipEmptyParts);
-    result2.removeAll(QString());
-    QVERIFY(list2 == result2);
-
-    QString str3 = "Now: this sentence fragment.";
-    QStringList list3 = str3.split(QRegExp("\\b"));
-    QStringList result3;
-    result3 << "" << "Now" << ": " << "this" << " " << "sentence" << " " << "fragment" << ".";
-    QVERIFY(list3 == result3);
-    list3 = str3.split(QRegExp("\\b"), QString::SkipEmptyParts);
-    result3.removeAll(QString());
-    QVERIFY(list3 == result3);
+    QFETCH(QString, string);
+    QFETCH(QString, pattern);
+    QFETCH(QStringList, result);
+
+    QStringList list;
+    list = string.split(QRegExp(pattern));
+    QCOMPARE(list, result);
+    list = string.split(QRegularExpression(pattern));
+    QCOMPARE(list, result);
+
+    result.removeAll(QString());
+
+    list = string.split(QRegExp(pattern), QString::SkipEmptyParts);
+    QCOMPARE(list, result);
+    list = string.split(QRegularExpression(pattern), QString::SkipEmptyParts);
+    QCOMPARE(list, result);
 }
 
 void tst_QString::fromUtf16_data()