diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 936a5d68fa..b9b261e27c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8476,6 +8476,25 @@ QString &QString::append(const QStringRef &str) return *this; } +/*! + \fn QStringRef::left(int n) const + \since 5.2 + + Returns a substring reference to the \a n leftmost characters + of the string. + + If \a n is greater than size() or less than zero, a reference to the entire + string is returned. + + \sa right(), mid(), startsWith() +*/ +QStringRef QStringRef::left(int n) const +{ + if (n >= m_size || n < 0) + return *this; + return QStringRef(m_string, m_position, n); +} + /*! \since 4.4 @@ -8496,6 +8515,25 @@ QStringRef QString::leftRef(int n) const return QStringRef(this, 0, n); } +/*! + \fn QStringRef::right(int n) const + \since 5.2 + + Returns a substring reference to the \a n rightmost characters + of the string. + + If \a n is greater than size() or less than zero, a reference to the entire + string is returned. + + \sa left(), mid(), endsWith() +*/ +QStringRef QStringRef::right(int n) const +{ + if (n >= m_size || n < 0) + return *this; + return QStringRef(m_string, n + m_position, m_size - n); +} + /*! \since 4.4 @@ -8516,6 +8554,40 @@ QStringRef QString::rightRef(int n) const return QStringRef(this, d->size - n, n); } +/*! + \fn QStringRef::mid(int position, int n = -1) const + \since 5.2 + + Returns a substring reference to \a n characters of this string, + starting at the specified \a position. + + If the \a position exceeds the length of the string, a null + reference is returned. + + If there are less than \a n characters available in the string, + starting at the given \a position, or if \a n is -1 (default), the + function returns all characters from the specified \a position + onwards. + + \sa left(), right() +*/ +QStringRef QStringRef::mid(int pos, int n) const +{ + if (pos > m_size) + return QStringRef(); + if (pos < 0) { + if (n < 0 || n + pos >= m_size) + return QStringRef(m_string, m_position, m_size); + if (n + pos <= 0) + return QStringRef(); + n += pos; + pos = 0; + } else if (n < 0 || n > m_size - pos) { + n = m_size - pos; + } + return QStringRef(m_string, pos + m_position, n); +} + /*! \since 4.4 @@ -8536,7 +8608,6 @@ QStringRef QString::rightRef(int n) const \sa mid(), leftRef(), rightRef() */ - QStringRef QString::midRef(int position, int n) const { if (position > d->size) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 7010a954b4..d20b3e227d 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1226,6 +1226,10 @@ public: int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + 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; + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp index 1045d5929f..7bbcee8ab2 100644 --- a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp +++ b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp @@ -88,6 +88,9 @@ private slots: void integer_conversion_data(); void integer_conversion(); void trimmed(); + void left(); + void right(); + void mid(); }; static QStringRef emptyRef() @@ -1794,6 +1797,145 @@ void tst_QStringRef::trimmed() QCOMPARE(b.trimmed().compare(QStringLiteral("a")), 0); } +void tst_QStringRef::left() +{ + QString originalString = "OrginalString~"; + QStringRef ref = originalString.leftRef(originalString.size() - 1); + QCOMPARE(ref.toString(), QStringLiteral("OrginalString")); + + QVERIFY(ref.left(0).toString().isEmpty()); + QCOMPARE(ref.left(ref.size()).toString(), QStringLiteral("OrginalString")); + + QStringRef nullRef; + QVERIFY(nullRef.isNull()); + QVERIFY(nullRef.left(3).toString().isEmpty()); + QVERIFY(nullRef.left(0).toString().isEmpty()); + QVERIFY(nullRef.left(-1).toString().isEmpty()); + + QStringRef emptyRef(&originalString, 0, 0); + QVERIFY(emptyRef.isEmpty()); + QVERIFY(emptyRef.left(3).toString().isEmpty()); + QVERIFY(emptyRef.left(0).toString().isEmpty()); + QVERIFY(emptyRef.left(-1).toString().isEmpty()); + + QCOMPARE(ref.left(-1), ref); + QCOMPARE(ref.left(100), ref); +} + +void tst_QStringRef::right() +{ + QString originalString = "~OrginalString"; + QStringRef ref = originalString.rightRef(originalString.size() - 1); + QCOMPARE(ref.toString(), QLatin1String("OrginalString")); + + QCOMPARE(ref.right(ref.size() - 6).toString(), QLatin1String("String")); + QCOMPARE(ref.right(ref.size()).toString(), QLatin1String("OrginalString")); + QCOMPARE(ref.right(0).toString(), QLatin1String("OrginalString")); + + QStringRef nullRef; + QVERIFY(nullRef.isNull()); + QVERIFY(nullRef.right(3).toString().isEmpty()); + QVERIFY(nullRef.right(0).toString().isEmpty()); + QVERIFY(nullRef.right(-1).toString().isEmpty()); + + QStringRef emptyRef(&originalString, 0, 0); + QVERIFY(emptyRef.isEmpty()); + QVERIFY(emptyRef.right(3).toString().isEmpty()); + QVERIFY(emptyRef.right(0).toString().isEmpty()); + QVERIFY(emptyRef.right(-1).toString().isEmpty()); + + QCOMPARE(ref.right(-1), ref); + QCOMPARE(ref.right(100), ref); +} + +void tst_QStringRef::mid() +{ + QString orig = QStringLiteral("~ABCDEFGHIEfGEFG~"); // 15 + 2 chars + QStringRef a = orig.midRef(1, 15); + QCOMPARE(a.size(), orig.size() - 2); + + QCOMPARE(a.mid(3,3).toString(),(QString)"DEF"); + QCOMPARE(a.mid(0,0).toString(),(QString)""); + QVERIFY(!a.mid(15,0).toString().isNull()); + QVERIFY(a.mid(15,0).toString().isEmpty()); + QVERIFY(!a.mid(15,1).toString().isNull()); + QVERIFY(a.mid(15,1).toString().isEmpty()); + QVERIFY(a.mid(9999).toString().isEmpty()); + QVERIFY(a.mid(9999,1).toString().isEmpty()); + + QCOMPARE(a.mid(-1, 6), a.mid(0, 5)); + QVERIFY(a.mid(-100, 6).isEmpty()); + QVERIFY(a.mid(INT_MIN, 0).isEmpty()); + QCOMPARE(a.mid(INT_MIN, -1), a); + QVERIFY(a.mid(INT_MIN, INT_MAX).isNull()); + QVERIFY(a.mid(INT_MIN + 1, INT_MAX).isEmpty()); + QCOMPARE(a.mid(INT_MIN + 2, INT_MAX), a.left(1)); + QCOMPARE(a.mid(INT_MIN + a.size() + 1, INT_MAX), a); + QVERIFY(a.mid(INT_MAX).isNull()); + QVERIFY(a.mid(INT_MAX, INT_MAX).isNull()); + QCOMPARE(a.mid(-5, INT_MAX), a); + QCOMPARE(a.mid(-1, INT_MAX), a); + QCOMPARE(a.mid(0, INT_MAX), a); + QCOMPARE(a.mid(1, INT_MAX).toString(), QString("BCDEFGHIEfGEFG")); + QCOMPARE(a.mid(5, INT_MAX).toString(), QString("FGHIEfGEFG")); + QVERIFY(a.mid(20, INT_MAX).isNull()); + QCOMPARE(a.mid(-1, -1), a); + + QStringRef nullRef; + QVERIFY(nullRef.mid(3,3).toString().isEmpty()); + QVERIFY(nullRef.mid(0,0).toString().isEmpty()); + QVERIFY(nullRef.mid(9999,0).toString().isEmpty()); + QVERIFY(nullRef.mid(9999,1).toString().isEmpty()); + + QVERIFY(nullRef.mid(-1, 6).isNull()); + QVERIFY(nullRef.mid(-100, 6).isNull()); + QVERIFY(nullRef.mid(INT_MIN, 0).isNull()); + QVERIFY(nullRef.mid(INT_MIN, -1).isNull()); + QVERIFY(nullRef.mid(INT_MIN, INT_MAX).isNull()); + QVERIFY(nullRef.mid(INT_MIN + 1, INT_MAX).isNull()); + QVERIFY(nullRef.mid(INT_MIN + 2, INT_MAX).isNull()); + QVERIFY(nullRef.mid(INT_MIN + nullRef.size() + 1, INT_MAX).isNull()); + QVERIFY(nullRef.mid(INT_MAX).isNull()); + QVERIFY(nullRef.mid(INT_MAX, INT_MAX).isNull()); + QVERIFY(nullRef.mid(-5, INT_MAX).isNull()); + QVERIFY(nullRef.mid(-1, INT_MAX).isNull()); + QVERIFY(nullRef.mid(0, INT_MAX).isNull()); + QVERIFY(nullRef.mid(1, INT_MAX).isNull()); + QVERIFY(nullRef.mid(5, INT_MAX).isNull()); + QVERIFY(nullRef.mid(20, INT_MAX).isNull()); + QVERIFY(nullRef.mid(-1, -1).isNull()); + + QString ninePineapples = "~Nine pineapples~"; + QStringRef x = ninePineapples.midRef(1, ninePineapples.size() - 1); + QCOMPARE(x.mid(5, 4).toString(), QString("pine")); + QCOMPARE(x.mid(5).toString(), QString("pineapples~")); + + QCOMPARE(x.mid(-1, 6), x.mid(0, 5)); + QVERIFY(x.mid(-100, 6).isEmpty()); + QVERIFY(x.mid(INT_MIN, 0).isEmpty()); + QCOMPARE(x.mid(INT_MIN, -1).toString(), x.toString()); + QVERIFY(x.mid(INT_MIN, INT_MAX).isNull()); + QVERIFY(x.mid(INT_MIN + 1, INT_MAX).isEmpty()); + QCOMPARE(x.mid(INT_MIN + 2, INT_MAX), x.left(1)); + QCOMPARE(x.mid(INT_MIN + x.size() + 1, INT_MAX).toString(), x.toString()); + QVERIFY(x.mid(INT_MAX).isNull()); + QVERIFY(x.mid(INT_MAX, INT_MAX).isNull()); + QCOMPARE(x.mid(-5, INT_MAX).toString(), x.toString()); + QCOMPARE(x.mid(-1, INT_MAX).toString(), x.toString()); + QCOMPARE(x.mid(0, INT_MAX), x); + QCOMPARE(x.mid(1, INT_MAX).toString(), QString("ine pineapples~")); + QCOMPARE(x.mid(5, INT_MAX).toString(), QString("pineapples~")); + QVERIFY(x.mid(20, INT_MAX).isNull()); + QCOMPARE(x.mid(-1, -1), x); + + QStringRef emptyRef(&ninePineapples, 0, 0); + QVERIFY(emptyRef.mid(1).isEmpty()); + QVERIFY(emptyRef.mid(-1).isEmpty()); + QVERIFY(emptyRef.mid(0).isEmpty()); + QVERIFY(emptyRef.mid(0, 3).isEmpty()); + QVERIFY(emptyRef.mid(-10, 3).isEmpty()); +} + QTEST_APPLESS_MAIN(tst_QStringRef) #include "tst_qstringref.moc"