summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp14
-rw-r--r--src/corelib/global/qglobal.h4
-rw-r--r--src/corelib/io/qdatastream.cpp1
-rw-r--r--src/corelib/io/qdatastream.h5
-rw-r--r--src/corelib/kernel/qmetatype.h3
-rw-r--r--src/corelib/tools/qbytearray.cpp179
-rw-r--r--src/corelib/tools/qbytearray.h25
-rw-r--r--src/corelib/tools/qdatetime.cpp32
-rw-r--r--src/corelib/tools/qstring.cpp451
-rw-r--r--src/corelib/tools/qstring.h33
-rw-r--r--src/corelib/tools/qstring_compat.cpp29
-rw-r--r--src/corelib/tools/qstringalgorithms_p.h135
-rw-r--r--src/corelib/tools/qstringiterator_p.h5
-rw-r--r--src/corelib/tools/tools.pri1
14 files changed, 556 insertions, 361 deletions
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index bf45a31c29..f5c6b69695 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -394,6 +394,13 @@ void Widget::firstIndexOfFunction()
QString str = "the minimum";
str.indexOf(QRegularExpression("m[aeiou]"), 0); // returns 4
//! [93]
+
+ //! [97]
+ QString str = "the minimum";
+ QRegularExpressionMatch match;
+ str.indexOf(QRegularExpression("m[aeiou]"), 0, &match); // returns 4
+ // match.captured() == mi
+ //! [97]
}
void Widget::insertFunction()
@@ -444,6 +451,13 @@ void Widget::lastIndexOfFunction()
QString str = "the minimum";
str.lastIndexOf(QRegularExpression("m[aeiou]")); // returns 8
//! [94]
+
+ //! [98]
+ QString str = "the minimum";
+ QRegularExpressionMatch match;
+ str.lastIndexOf(QRegularExpression("m[aeiou]"), -1, &match); // returns 8
+ // match.captured() == mu
+ //! [98]
}
void Widget::leftFunction()
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index dda870a4a1..9176d80f43 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -45,11 +45,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "5.4.0"
+#define QT_VERSION_STR "5.5.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050400
+#define QT_VERSION 0x050500
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 127244e994..8959984f0d 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -539,6 +539,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_2 Version 15 (Qt 5.2)
\value Qt_5_3 Same as Qt_5_2
\value Qt_5_4 Version 16 (Qt 5.4)
+ \value Qt_5_5 Same as Qt_5_4
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 808fbe73f6..f5d5dca451 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -90,10 +90,11 @@ public:
Qt_5_2 = 15,
Qt_5_3 = Qt_5_2,
Qt_5_4 = 16,
-#if QT_VERSION >= 0x050500
+ Qt_5_5 = Qt_5_4,
+#if QT_VERSION >= 0x050600
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_4
+ Qt_DefaultCompiledVersion = Qt_5_5
};
enum ByteOrder {
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 7870ea5236..7570a6fb20 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1520,6 +1520,9 @@ struct QMetaTypeId2
template <typename T>
struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
+template <typename T>
+struct QMetaTypeId2<T&> { enum {Defined = false }; };
+
namespace QtPrivate {
template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
struct QMetaTypeIdHelper {
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 088a7c1769..9c22821155 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -46,6 +47,7 @@
#include "qlist.h"
#include "qlocale.h"
#include "qlocale_p.h"
+#include "qstringalgorithms_p.h"
#include "qscopedpointer.h"
#include <qdatastream.h>
#include <qmath.h>
@@ -62,6 +64,64 @@
QT_BEGIN_NAMESPACE
+// Latin 1 case system, used by QByteArray::to{Upper,Lower}() and qstr(n)icmp():
+/*
+#!/usr/bin/perl -l
+use feature "unicode_strings";
+for (0..255) {
+ $up = uc(chr($_));
+ $up = chr($_) if ord($up) > 0x100 || length $up > 1;
+ printf "0x%02x,", ord($up);
+ print "" if ($_ & 0xf) == 0xf;
+}
+*/
+static const uchar latin1_uppercased[256] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
+ 0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x7b,0x7c,0x7d,0x7e,0x7f,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
+ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
+ 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
+ 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
+ 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
+ 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xf7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xff
+};
+
+/*
+#!/usr/bin/perl -l
+use feature "unicode_strings";
+for (0..255) {
+ $up = lc(chr($_));
+ $up = chr($_) if ord($up) > 0x100 || length $up > 1;
+ printf "0x%02x,", ord($up);
+ print "" if ($_ & 0xf) == 0xf;
+}
+*/
+static const uchar latin1_lowercased[256] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
+ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
+ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xd7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xdf,
+ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+};
int qFindByteArray(
const char *haystack0, int haystackLen, int from,
@@ -256,7 +316,7 @@ int qstricmp(const char *str1, const char *str2)
uchar c;
if (!s1 || !s2)
return s1 ? 1 : (s2 ? -1 : 0);
- for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++)
+ for (; !(res = (c = latin1_lowercased[*s1]) - latin1_lowercased[*s2]); s1++, s2++)
if (!c) // strings are equal
break;
return res;
@@ -291,7 +351,7 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
if (!s1 || !s2)
return s1 ? 1 : (s2 ? -1 : 0);
for (; len--; s1++, s2++) {
- if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)))
+ if ((res = (c = latin1_lowercased[*s1]) - latin1_lowercased[*s2]))
return res;
if (!c) // strings are equal
break;
@@ -2685,6 +2745,8 @@ QByteArray QByteArray::mid(int pos, int len) const
}
/*!
+ \fn QByteArray QByteArray::toLower() const
+
Returns a lowercase copy of the byte array. The bytearray is
interpreted as a Latin-1 encoded string.
@@ -2693,21 +2755,56 @@ QByteArray QByteArray::mid(int pos, int len) const
\sa toUpper(), {8-bit Character Comparisons}
*/
-QByteArray QByteArray::toLower() const
+
+// noinline so that the compiler won't inline the function in each of
+// toLower and toUpper when the only difference is the table being used
+// (even with constant propagation, there's no gain in performance).
+template <typename T>
+#ifdef Q_CC_MSVC
+__declspec(noinline)
+#elif defined(Q_CC_GNU)
+__attribute__((noinline))
+#endif
+static QByteArray toCase_template(T &input, const uchar * table)
{
- QByteArray s(*this);
- uchar *p = reinterpret_cast<uchar *>(s.data());
- uchar *e = reinterpret_cast<uchar *>(s.end());
- if (p) {
- while (p != e) {
- *p = QChar::toLower((ushort)*p);
- p++;
- }
+ // find the first bad character in input
+ const char *orig_begin = input.constBegin();
+ const char *firstBad = orig_begin;
+ const char *e = input.constEnd();
+ for ( ; firstBad != e ; ++firstBad) {
+ uchar ch = uchar(*firstBad);
+ uchar converted = table[ch];
+ if (ch != converted)
+ break;
+ }
+
+ if (firstBad == e)
+ return qMove(input);
+
+ // transform the rest
+ QByteArray s = qMove(input); // will copy if T is const QByteArray
+ char *b = s.begin(); // will detach if necessary
+ char *p = b + (firstBad - orig_begin);
+ e = b + s.size();
+ for ( ; p != e; ++p) {
+ *p = char(uchar(table[uchar(*p)]));
}
return s;
}
+QByteArray QByteArray::toLower_helper(const QByteArray &a)
+{
+ return toCase_template(a, latin1_lowercased);
+}
+
+QByteArray QByteArray::toLower_helper(QByteArray &a)
+{
+ return toCase_template(a, latin1_lowercased);
+}
+
/*!
+ \fn QByteArray QByteArray::toUpper() const
+
Returns an uppercase copy of the byte array. The bytearray is
interpreted as a Latin-1 encoded string.
@@ -2717,18 +2814,14 @@ QByteArray QByteArray::toLower() const
\sa toLower(), {8-bit Character Comparisons}
*/
-QByteArray QByteArray::toUpper() const
+QByteArray QByteArray::toUpper_helper(const QByteArray &a)
{
- QByteArray s(*this);
- uchar *p = reinterpret_cast<uchar *>(s.data());
- uchar *e = reinterpret_cast<uchar *>(s.end());
- if (p) {
- while (p != e) {
- *p = QChar::toUpper((ushort)*p);
- p++;
- }
- }
- return s;
+ return toCase_template(a, latin1_uppercased);
+}
+
+QByteArray QByteArray::toUpper_helper(QByteArray &a)
+{
+ return toCase_template(a, latin1_uppercased);
}
/*! \fn void QByteArray::clear()
@@ -3123,27 +3216,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
*/
QByteArray QByteArray::simplified() const
{
- if (d->size == 0)
- return *this;
- QByteArray result(d->size, Qt::Uninitialized);
- const char *from = d->data();
- const char *fromend = from + d->size;
- int outc=0;
- char *to = result.d->data();
- for (;;) {
- while (from!=fromend && ascii_isspace(uchar(*from)))
- from++;
- while (from!=fromend && !ascii_isspace(uchar(*from)))
- to[outc++] = *from++;
- if (from!=fromend)
- to[outc++] = ' ';
- else
- break;
- }
- if (outc > 0 && to[outc-1] == ' ')
- outc--;
- result.resize(outc);
- return result;
+ return QStringAlgorithms<const QByteArray>::simplified_helper(*this);
}
/*!
@@ -3163,25 +3236,7 @@ QByteArray QByteArray::simplified() const
*/
QByteArray QByteArray::trimmed() const
{
- if (d->size == 0)
- return *this;
- const char *s = d->data();
- if (!ascii_isspace(uchar(*s)) && !ascii_isspace(uchar(s[d->size-1])))
- return *this;
- int start = 0;
- int end = d->size - 1;
- while (start<=end && ascii_isspace(uchar(s[start]))) // skip white space from start
- start++;
- if (start <= end) { // only white space
- while (end && ascii_isspace(uchar(s[end]))) // skip white space from end
- end--;
- }
- int l = end - start + 1;
- if (l <= 0) {
- QByteArrayDataPtr empty = { Data::allocate(0) };
- return QByteArray(empty);
- }
- return QByteArray(s+start, l);
+ return QStringAlgorithms<const QByteArray>::trimmed_helper(*this);
}
/*!
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index ba7fdbb10a..cb1ebf8493 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -264,8 +264,29 @@ public:
void truncate(int pos);
void chop(int n);
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
+# if defined(Q_CC_GNU)
+ // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
+# pragma push_macro("Q_REQUIRED_RESULT")
+# undef Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT_pushed
+# endif
+ QByteArray toLower() const & Q_REQUIRED_RESULT
+ { return toLower_helper(*this); }
+ QByteArray toLower() && Q_REQUIRED_RESULT
+ { return toLower_helper(*this); }
+ QByteArray toUpper() const & Q_REQUIRED_RESULT
+ { return toUpper_helper(*this); }
+ QByteArray toUpper() && Q_REQUIRED_RESULT
+ { return toUpper_helper(*this); }
+# ifdef Q_REQUIRED_RESULT_pushed
+# pragma pop_macro("Q_REQUIRED_RESULT")
+# endif
+#else
QByteArray toLower() const Q_REQUIRED_RESULT;
QByteArray toUpper() const Q_REQUIRED_RESULT;
+#endif
QByteArray trimmed() const Q_REQUIRED_RESULT;
QByteArray simplified() const Q_REQUIRED_RESULT;
@@ -422,6 +443,10 @@ private:
void expand(int i);
QByteArray nulTerminated() const;
+ static QByteArray toLower_helper(const QByteArray &a);
+ static QByteArray toLower_helper(QByteArray &a);
+ static QByteArray toUpper_helper(const QByteArray &a);
+ static QByteArray toUpper_helper(QByteArray &a);
friend class QByteRef;
friend class QString;
friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes);
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 3c01edc83e..328d666bd5 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -257,7 +257,7 @@ static QString toOffsetString(Qt::DateFormat format, int offset)
}
// Parse offset in [+-]HH[:]MM format
-static int fromOffsetString(const QString &offsetString, bool *valid)
+static int fromOffsetString(const QStringRef &offsetString, bool *valid)
{
*valid = false;
@@ -278,15 +278,15 @@ static int fromOffsetString(const QString &offsetString, bool *valid)
return 0;
// Split the hour and minute parts
- QStringList parts = offsetString.mid(1).split(QLatin1Char(':'));
+ QVector<QStringRef> parts = offsetString.mid(1).split(QLatin1Char(':'));
if (parts.count() == 1) {
// [+-]HHMM format
- parts.append(parts.at(0).mid(2));
- parts[0] = parts.at(0).left(2);
+ parts.append(parts.first().mid(2));
+ parts[0] = parts.first().left(2);
}
bool ok = false;
- const int hour = parts.at(0).toInt(&ok);
+ const int hour = parts.first().toInt(&ok);
if (!ok)
return 0;
@@ -1255,12 +1255,12 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format)
default:
#ifndef QT_NO_TEXTDATE
case Qt::TextDate: {
- QStringList parts = string.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
if (parts.count() != 4)
return QDate();
- QString monthName = parts.at(1);
+ QStringRef monthName = parts.at(1);
int month = -1;
// Assume that English monthnames are the default
for (int i = 0; i < 12; ++i) {
@@ -4358,7 +4358,7 @@ int QDateTime::utcOffset() const
#ifndef QT_NO_DATESTRING
-static int fromShortMonthName(const QString &monthName)
+static int fromShortMonthName(const QStringRef &monthName)
{
// Assume that English monthnames are the default
for (int i = 0; i < 12; ++i) {
@@ -4450,7 +4450,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (found) {
bool ok;
- offset = fromOffsetString(isoString.mid(signIndex).toString(), &ok);
+ offset = fromOffsetString(isoString.mid(signIndex), &ok);
if (!ok)
return QDateTime();
isoString = isoString.left(signIndex);
@@ -4470,7 +4470,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
}
#if !defined(QT_NO_TEXTDATE)
case Qt::TextDate: {
- QStringList parts = string.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
if ((parts.count() < 5) || (parts.count() > 6))
return QDateTime();
@@ -4489,9 +4489,9 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (!month || !day) {
month = fromShortMonthName(parts.at(2));
if (month) {
- QString dayStr = parts.at(1);
+ QStringRef dayStr = parts.at(1);
if (dayStr.endsWith(QLatin1Char('.'))) {
- dayStr.chop(1);
+ dayStr = dayStr.left(dayStr.size() - 1);
day = dayStr.toInt();
}
}
@@ -4524,7 +4524,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (!date.isValid())
return QDateTime();
- QStringList timeParts = parts.at(timePart).split(QLatin1Char(':'));
+ QVector<QStringRef> timeParts = parts.at(timePart).split(QLatin1Char(':'));
if (timeParts.count() < 2 || timeParts.count() > 3)
return QDateTime();
@@ -4539,7 +4539,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
int second = 0;
int millisecond = 0;
if (timeParts.count() > 2) {
- QStringList secondParts = timeParts.at(2).split(QLatin1Char('.'));
+ QVector<QStringRef> secondParts = timeParts.at(2).split(QLatin1Char('.'));
if (secondParts.size() > 2) {
return QDateTime();
}
@@ -4564,10 +4564,10 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (parts.count() == 5)
return QDateTime(date, time, Qt::LocalTime);
- QString tz = parts.at(5);
+ QStringRef tz = parts.at(5);
if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
return QDateTime();
- tz.remove(0, 3);
+ tz = tz.mid(3);
if (!tz.isEmpty()) {
int offset = fromOffsetString(tz, &ok);
if (!ok)
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 2ce8a3a45b..e7bad15b5d 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -78,6 +78,7 @@
#include "qchar.cpp"
#include "qstringmatcher.cpp"
#include "qstringiterator_p.h"
+#include "qstringalgorithms_p.h"
#include "qthreadstorage.h"
#ifdef Q_OS_WIN
@@ -3676,14 +3677,39 @@ int QString::count(const QRegExp& rx) const
*/
int QString::indexOf(const QRegularExpression& re, int from) const
{
+ return indexOf(re, from, Q_NULLPTR);
+}
+
+/*!
+ \overload
+ \since 5.5
+
+ 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.
+
+ If the match is successful and \a rmatch is not a null pointer, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ Example:
+
+ \snippet qstring/main.cpp 97
+*/
+int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
+{
if (!re.isValid()) {
qWarning("QString::indexOf: invalid QRegularExpression object");
return -1;
}
QRegularExpressionMatch match = re.match(*this, from);
- if (match.hasMatch())
- return match.capturedStart();
+ if (match.hasMatch()) {
+ const int ret = match.capturedStart();
+ if (rmatch)
+ *rmatch = qMove(match);
+ return ret;
+ }
return -1;
}
@@ -3702,22 +3728,45 @@ int QString::indexOf(const QRegularExpression& re, int from) const
*/
int QString::lastIndexOf(const QRegularExpression &re, int from) const
{
+ return lastIndexOf(re, from, Q_NULLPTR);
+}
+
+/*!
+ \overload
+ \since 5.5
+
+ 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.
+
+ If the match is successful and \a rmatch is not a null pointer, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ Example:
+
+ \snippet qstring/main.cpp 98
+*/
+int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
+{
if (!re.isValid()) {
qWarning("QString::lastIndexOf: invalid QRegularExpression 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)
+ if (start < endpos) {
lastIndex = start;
- else
+ if (rmatch)
+ *rmatch = qMove(match);
+ } else {
break;
+ }
}
return lastIndex;
@@ -3731,12 +3780,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const
*/
bool QString::contains(const QRegularExpression &re) const
{
- if (!re.isValid()) {
- qWarning("QString::contains: invalid QRegularExpression object");
- return false;
- }
- QRegularExpressionMatch match = re.match(*this);
- return match.hasMatch();
+ return contains(re, Q_NULLPTR);
}
/*!
@@ -3756,13 +3800,13 @@ bool QString::contains(const QRegularExpression &re) const
bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *match) const
{
if (!re.isValid()) {
- qWarning("QString::contains: invalid QRegularExpresssion object");
+ qWarning("QString::contains: invalid QRegularExpression object");
return false;
}
QRegularExpressionMatch m = re.match(*this);
bool hasMatch = m.hasMatch();
if (hasMatch && match)
- *match = m;
+ *match = qMove(m);
return hasMatch;
}
@@ -3921,12 +3965,14 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
#if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION))
class qt_section_chunk {
public:
+ qt_section_chunk() {}
qt_section_chunk(int l, QString s) { length = l; string = s; }
int length;
QString string;
};
+Q_DECLARE_TYPEINFO(qt_section_chunk, Q_MOVABLE_TYPE);
-static QString extractSections(const QList<qt_section_chunk> &sections,
+static QString extractSections(const QVector<qt_section_chunk> &sections,
int start,
int end,
QString::SectionFlags flags)
@@ -3994,7 +4040,7 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive
: Qt::CaseSensitive);
- QList<qt_section_chunk> sections;
+ 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, QString(uc + last_m, m - last_m)));
@@ -4039,7 +4085,7 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
if (flags & SectionCaseInsensitiveSeps)
sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption);
- QList<qt_section_chunk> sections;
+ QVector<qt_section_chunk> sections;
int n = length(), m = 0, last_m = 0, last_len = 0;
QRegularExpressionMatchIterator iterator = sep.globalMatch(*this);
while (iterator.hasNext()) {
@@ -4633,78 +4679,7 @@ QString& QString::setUnicode(const QChar *unicode, int size)
*/
QString QString::simplified() const
{
- if (d->size == 0)
- return *this;
-
- const QChar * const start = reinterpret_cast<QChar *>(d->data());
- const QChar *from = start;
- const QChar *fromEnd = start + d->size;
- forever {
- QChar ch = *from;
- if (!ch.isSpace())
- break;
- if (++from == fromEnd) {
- // All-whitespace string
- QStringDataPtr empty = { Data::allocate(0) };
- return QString(empty);
- }
- }
- // This loop needs no underflow check, as we already determined that
- // the string contains non-whitespace. If the string has exactly one
- // non-whitespace, it will be checked twice - we can live with that.
- while (fromEnd[-1].isSpace())
- fromEnd--;
- // The rest of the function depends on the fact that we already know
- // that the last character in the source is no whitespace.
- const QChar *copyFrom = from;
- int copyCount;
- forever {
- if (++from == fromEnd) {
- // Only leading and/or trailing whitespace, if any at all
- return mid(copyFrom - start, from - copyFrom);
- }
- QChar ch = *from;
- if (!ch.isSpace())
- continue;
- if (ch != QLatin1Char(' ')) {
- copyCount = from - copyFrom;
- break;
- }
- ch = *++from;
- if (ch.isSpace()) {
- copyCount = from - copyFrom - 1;
- break;
- }
- }
- // 'from' now points at the non-trailing whitespace which made the
- // string not simplified in the first place. 'copyCount' is the number
- // of already simplified characters - at least one, obviously -
- // without a trailing space.
- QString result((fromEnd - from) + copyCount, Qt::Uninitialized);
- QChar *to = reinterpret_cast<QChar *>(result.d->data());
- ::memcpy(to, copyFrom, copyCount * 2);
- to += copyCount;
- fromEnd--;
- QChar ch;
- forever {
- *to++ = QLatin1Char(' ');
- do {
- ch = *++from;
- } while (ch.isSpace());
- if (from == fromEnd)
- break;
- do {
- *to++ = ch;
- ch = *++from;
- if (from == fromEnd)
- goto done;
- } while (!ch.isSpace());
-
- }
- done:
- *to++ = ch;
- result.truncate(to - reinterpret_cast<QChar *>(result.d->data()));
- return result;
+ return QStringAlgorithms<const QString>::simplified_helper(*this);
}
/*!
@@ -4725,25 +4700,7 @@ QString QString::simplified() const
*/
QString QString::trimmed() const
{
- if (d->size == 0)
- return *this;
- const QChar *s = (const QChar*)d->data();
- if (!s->isSpace() && !s[d->size-1].isSpace())
- return *this;
- int start = 0;
- int end = d->size - 1;
- while (start<=end && s[start].isSpace()) // skip white space from start
- start++;
- if (start <= end) { // only white space
- while (end && s[end].isSpace()) // skip white space from end
- end--;
- }
- int l = end - start + 1;
- if (l <= 0) {
- QStringDataPtr empty = { Data::allocate(0) };
- return QString(empty);
- }
- return QString(s + start, l);
+ return QStringAlgorithms<const QString>::trimmed_helper(*this);
}
/*! \fn const QChar QString::at(int position) const
@@ -5510,6 +5467,8 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
}
/*!
+ \fn QString QString::toLower() const
+
Returns a lowercase copy of the string.
\snippet qstring/main.cpp 75
@@ -5520,132 +5479,118 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
\sa toUpper(), QLocale::toLower()
*/
-QString QString::toLower() const
+namespace QUnicodeTables {
+struct LowercaseTraits
{
- const ushort *p = d->data();
- if (!p)
- return *this;
+ static signed short caseDiff(const Properties *prop)
+ { return prop->lowerCaseDiff; }
+ static bool caseSpecial(const Properties *prop)
+ { return prop->lowerCaseSpecial; }
+};
- const ushort *e = p + d->size;
- // this avoids out of bounds check in the loop
- while (e != p && QChar::isHighSurrogate(*(e - 1)))
- --e;
+struct UppercaseTraits
+{
+ static signed short caseDiff(const Properties *prop)
+ { return prop->upperCaseDiff; }
+ static bool caseSpecial(const Properties *prop)
+ { return prop->upperCaseSpecial; }
+};
- const QUnicodeTables::Properties *prop;
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- ushort high = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(high, *p));
+struct CasefoldTraits
+{
+ static signed short caseDiff(const Properties *prop)
+ { return prop->caseFoldDiff; }
+ static bool caseSpecial(const Properties *prop)
+ { return prop->caseFoldSpecial; }
+};
+
+template <typename Traits, typename T>
+#ifdef Q_CC_MSVC
+__declspec(noinline)
+#elif defined(Q_CC_GNU)
+__attribute__((noinline))
+#endif
+static QString detachAndConvertCase(T &str, QStringIterator it)
+{
+ QString s = qMove(str); // will copy if T is const QString
+ QChar *pp = s.begin() + it.index(); // will detach if necessary
+ uint uc = it.nextUnchecked();
+ forever {
+ const QUnicodeTables::Properties *prop = qGetProp(uc);
+ signed short caseDiff = Traits::caseDiff(prop);
+
+ if (Q_UNLIKELY(Traits::caseSpecial(prop))) {
+ // slow path
+ const ushort *specialCase = specialCaseMap + caseDiff;
+ ushort length = *specialCase++;
+ int pos = pp - s.constBegin();
+ s.replace(pos, 1, reinterpret_cast<const QChar *>(specialCase), length);
+ pp = const_cast<QChar *>(s.constBegin()) + pos + length;
+ } else if (QChar::requiresSurrogates(uc)) {
+ *pp++ = QChar::highSurrogate(uc + caseDiff);
+ *pp++ = QChar::lowSurrogate(uc + caseDiff);
} else {
- prop = qGetProp(*p);
+ *pp++ = QChar(uc + caseDiff);
}
- if (prop->lowerCaseDiff) {
- if (QChar::isLowSurrogate(*p))
- --p; // safe; diff is 0 for surrogates
- QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
- ushort *pp = s.d->data() + (p - d->data());
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- *pp = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p));
- } else {
- prop = qGetProp(*p);
- }
- if (prop->lowerCaseSpecial) {
- const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff;
- ushort length = *specialCase++;
- int pos = pp - s.d->data();
- s.resize(s.d->size + length - 1);
- pp = s.d->data() + pos;
- while (length--)
- *pp++ = *specialCase++;
- } else {
- *pp++ = *p + prop->lowerCaseDiff;
- }
- ++p;
- }
-
- // this restores high surrogate parts eaten above, if any
- while (e != d->data() + d->size)
- *pp++ = *e++;
+ if (!it.hasNext())
return s;
- }
- ++p;
+
+ uc = it.nextUnchecked();
}
- return *this;
}
-/*!
- Returns the case folded equivalent of the string. For most Unicode
- characters this is the same as toLower().
-*/
-QString QString::toCaseFolded() const
+template <typename Traits, typename T>
+static QString convertCase(T &str)
{
- const ushort *p = d->data();
- if (!p)
- return *this;
+ const QChar *p = str.constBegin();
+ const QChar *e = p + str.size();
- const ushort *e = p + d->size;
// this avoids out of bounds check in the loop
- while (e != p && QChar::isHighSurrogate(*(e - 1)))
+ while (e != p && e[-1].isHighSurrogate())
--e;
const QUnicodeTables::Properties *prop;
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- ushort high = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(high, *p));
- } else {
- prop = qGetProp(*p);
- }
- if (prop->caseFoldDiff) {
- if (QChar::isLowSurrogate(*p))
- --p; // safe; diff is 0 for surrogates
- QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
- ushort *pp = s.d->data() + (p - d->data());
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- *pp = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p));
- } else {
- prop = qGetProp(*p);
- }
- if (prop->caseFoldSpecial) {
- const ushort *specialCase = specialCaseMap + prop->caseFoldDiff;
- ushort length = *specialCase++;
-#if 0
- int pos = pp - s.d->data;
- s.resize(s.d->size + length - 1);
- pp = s.d->data + pos;
- while (length--)
- *pp++ = *specialCase++;
-#else
- //### we currently don't support full case foldings
- Q_ASSERT(length == 1);
- Q_UNUSED(length)
- *pp++ = *specialCase;
-#endif
- } else {
- *pp++ = *p + prop->caseFoldDiff;
- }
- ++p;
- }
+ QStringIterator it(p, e);
+ for ( ; it.hasNext(); it.advanceUnchecked()) {
+ prop = qGetProp(it.peekNextUnchecked());
+ if (Traits::caseDiff(prop))
+ return detachAndConvertCase<Traits>(str, it);
+ }
+ return qMove(str);
+}
+} // namespace QUnicodeTables
- // this restores high surrogate parts eaten above, if any
- while (e != d->data() + d->size)
- *pp++ = *e++;
+QString QString::toLower_helper(const QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::LowercaseTraits>(str);
+}
- return s;
- }
- ++p;
- }
- return *this;
+QString QString::toLower_helper(QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::LowercaseTraits>(str);
}
/*!
+ \fn QString QString::toCaseFolded() const
+
+ Returns the case folded equivalent of the string. For most Unicode
+ characters this is the same as toLower().
+*/
+
+QString QString::toCaseFolded_helper(const QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::CasefoldTraits>(str);
+}
+
+QString QString::toCaseFolded_helper(QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::CasefoldTraits>(str);
+}
+
+/*!
+ \fn QString QString::toUpper() const
+
Returns an uppercase copy of the string.
\snippet qstring/main.cpp 81
@@ -5655,63 +5600,18 @@ QString QString::toCaseFolded() const
\sa toLower(), QLocale::toLower()
*/
-QString QString::toUpper() const
-{
- const ushort *p = d->data();
- if (!p)
- return *this;
-
- const ushort *e = p + d->size;
- // this avoids out of bounds check in the loop
- while (e != p && QChar::isHighSurrogate(*(e - 1)))
- --e;
-
- const QUnicodeTables::Properties *prop;
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- ushort high = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(high, *p));
- } else {
- prop = qGetProp(*p);
- }
- if (prop->upperCaseDiff) {
- if (QChar::isLowSurrogate(*p))
- --p; // safe; diff is 0 for surrogates
- QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
- ushort *pp = s.d->data() + (p - d->data());
- while (p != e) {
- if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
- *pp = *p++;
- prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p));
- } else {
- prop = qGetProp(*p);
- }
- if (prop->upperCaseSpecial) {
- const ushort *specialCase = specialCaseMap + prop->upperCaseDiff;
- ushort length = *specialCase++;
- int pos = pp - s.d->data();
- s.resize(s.d->size + length - 1);
- pp = s.d->data() + pos;
- while (length--)
- *pp++ = *specialCase++;
- } else {
- *pp++ = *p + prop->upperCaseDiff;
- }
- ++p;
- }
- // this restores high surrogate parts eaten above, if any
- while (e != d->data() + d->size)
- *pp++ = *e++;
+QString QString::toUpper_helper(const QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str);
+}
- return s;
- }
- ++p;
- }
- return *this;
+QString QString::toUpper_helper(QString &str)
+{
+ return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str);
}
+
// ### Qt 6: Consider whether this function shouldn't be removed See task 202871.
/*!
Safely builds a formatted string from the format string \a cformat
@@ -9841,20 +9741,15 @@ QVector<uint> QStringRef::toUcs4() const
*/
QStringRef QStringRef::trimmed() const
{
- if (m_size == 0 || m_string == 0)
+ const QChar *begin = cbegin();
+ const QChar *end = cend();
+ QStringAlgorithms<const QStringRef>::trimmed_helper_positions(begin, end);
+ if (begin == cbegin() && end == cend())
return *this;
- const QChar *s = m_string->constData() + m_position;
- int start = 0;
- int end = m_size - 1;
- while (start <= end && s[start].isSpace()) // skip white space from start
- start++;
- if (start <= end) { // only white space
- while (end && s[end].isSpace()) // skip white space from end
- end--;
- }
- int l = end - start + 1;
- Q_ASSERT(l >= 0);
- return QStringRef(m_string, m_position + start, l);
+ if (begin == end)
+ return QStringRef();
+ int position = m_position + (begin - cbegin());
+ return QStringRef(m_string, position, end - begin);
}
/*!
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index dfb98ffaa2..dee76ceedd 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -335,7 +335,9 @@ public:
#ifndef QT_NO_REGULAREXPRESSION
int indexOf(const QRegularExpression &re, int from = 0) const;
+ int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
int lastIndexOf(const QRegularExpression &re, int from = -1) const;
+ int lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
bool contains(const QRegularExpression &re) const;
bool contains(const QRegularExpression &re, QRegularExpressionMatch *match) const; // ### Qt 6: merge overloads
int count(const QRegularExpression &re) const;
@@ -377,9 +379,34 @@ public:
QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT;
QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT;
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
+# if defined(Q_CC_GNU)
+ // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
+# pragma push_macro("Q_REQUIRED_RESULT")
+# undef Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT_pushed
+# endif
+ QString toLower() const & Q_REQUIRED_RESULT
+ { return toLower_helper(*this); }
+ QString toLower() && Q_REQUIRED_RESULT
+ { return toLower_helper(*this); }
+ QString toUpper() const & Q_REQUIRED_RESULT
+ { return toUpper_helper(*this); }
+ QString toUpper() && Q_REQUIRED_RESULT
+ { return toUpper_helper(*this); }
+ QString toCaseFolded() const & Q_REQUIRED_RESULT
+ { return toCaseFolded_helper(*this); }
+ QString toCaseFolded() && Q_REQUIRED_RESULT
+ { return toCaseFolded_helper(*this); }
+# ifdef Q_REQUIRED_RESULT_pushed
+# pragma pop_macro("Q_REQUIRED_RESULT")
+# endif
+#else
QString toLower() const Q_REQUIRED_RESULT;
QString toUpper() const Q_REQUIRED_RESULT;
QString toCaseFolded() const Q_REQUIRED_RESULT;
+#endif
QString trimmed() const Q_REQUIRED_RESULT;
QString simplified() const Q_REQUIRED_RESULT;
@@ -742,6 +769,12 @@ private:
Qt::CaseSensitivity cs = Qt::CaseSensitive);
static int localeAwareCompare_helper(const QChar *data1, int length1,
const QChar *data2, int length2);
+ static QString toLower_helper(const QString &str);
+ static QString toLower_helper(QString &str);
+ static QString toUpper_helper(const QString &str);
+ static QString toUpper_helper(QString &str);
+ static QString toCaseFolded_helper(const QString &str);
+ static QString toCaseFolded_helper(QString &str);
static Data *fromLatin1_helper(const char *str, int size = -1);
static Data *fromAscii_helper(const char *str, int size = -1);
static QString fromUtf8_helper(const char *str, int size);
diff --git a/src/corelib/tools/qstring_compat.cpp b/src/corelib/tools/qstring_compat.cpp
index 6613dfde8e..b42f49d86d 100644
--- a/src/corelib/tools/qstring_compat.cpp
+++ b/src/corelib/tools/qstring_compat.cpp
@@ -39,16 +39,32 @@
**
****************************************************************************/
-#if defined(QSTRING_H)
+#if defined(QSTRING_H) || defined(QBYTEARRAY_H)
# error "This file cannot be compiled with pre-compiled headers"
#endif
#define QT_COMPILING_QSTRING_COMPAT_CPP
+#include "qbytearray.h"
#include "qstring.h"
QT_BEGIN_NAMESPACE
// all these implementations must be the same as the inline versions in qstring.h
+QString QString::toLower() const
+{
+ return toLower_helper(*this);
+}
+
+QString QString::toCaseFolded() const
+{
+ return toCaseFolded_helper(*this);
+}
+
+QString QString::toUpper() const
+{
+ return toUpper_helper(*this);
+}
+
QByteArray QString::toLatin1() const
{
return toLatin1_helper(*this);
@@ -64,4 +80,15 @@ QByteArray QString::toUtf8() const
return toUtf8_helper(*this);
}
+// ditto, for qbytearray.h (because we're lazy)
+QByteArray QByteArray::toLower() const
+{
+ return toLower_helper(*this);
+}
+
+QByteArray QByteArray::toUpper() const
+{
+ return toUpper_helper(*this);
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h
new file mode 100644
index 0000000000..5a68260c59
--- /dev/null
+++ b/src/corelib/tools/qstringalgorithms_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Intel Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGALGORITHMS_P_H
+#define QSTRINGALGORITHMS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qstring.h"
+#include "qlocale_p.h" // for ascii_isspace
+
+QT_BEGIN_NAMESPACE
+
+template <typename StringType> struct QStringAlgorithms
+{
+ typedef typename StringType::value_type Char;
+ typedef typename StringType::size_type size_type;
+ typedef typename QtPrivate::remove_cv<StringType>::type NakedStringType;
+ static const bool isConst = QtPrivate::is_const<StringType>::value;
+
+ static inline bool isSpace(char ch) { return ascii_isspace(ch); }
+ static inline bool isSpace(QChar ch) { return ch.isSpace(); }
+
+ // Surrogate pairs are not handled in either of the functions below. That is
+ // not a problem because there are no space characters (Zs, Zl, Zp) outside the
+ // Basic Multilingual Plane.
+
+ static inline void trimmed_helper_positions(const Char *&begin, const Char *&end)
+ {
+ // skip white space from start
+ while (begin < end && isSpace(*begin))
+ begin++;
+ // skip white space from end
+ if (begin < end) {
+ while (begin < end && isSpace(end[-1]))
+ end--;
+ }
+ }
+
+ static inline StringType trimmed_helper(StringType &str)
+ {
+ const Char *begin = str.cbegin();
+ const Char *end = str.cend();
+ trimmed_helper_positions(begin, end);
+
+ if (begin == str.cbegin() && end == str.cend())
+ return str;
+ if (begin == end)
+ return StringType();
+ return StringType(begin, end - begin);
+ }
+
+ static inline StringType simplified_helper(StringType &str)
+ {
+ if (str.isEmpty())
+ return str;
+ const Char *src = str.cbegin();
+ const Char *end = str.cend();
+ NakedStringType result(str.size(), Qt::Uninitialized);
+
+ Char *dst = const_cast<Char *>(result.cbegin());
+ Char *ptr = dst;
+ forever {
+ while (src != end && isSpace(*src))
+ ++src;
+ while (src != end && !isSpace(*src))
+ *ptr++ = *src++;
+ if (src != end)
+ *ptr++ = QChar::Space;
+ else
+ break;
+ }
+ if (ptr != dst && ptr[-1] == QChar::Space)
+ --ptr;
+
+ int newlen = ptr - dst;
+ if (newlen == str.size()) {
+ // nothing happened, return the original
+ return str;
+ }
+ result.resize(ptr - dst);
+ return qMove(result);
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGALGORITHMS_P_H
diff --git a/src/corelib/tools/qstringiterator_p.h b/src/corelib/tools/qstringiterator_p.h
index c3986f0477..1e231792a2 100644
--- a/src/corelib/tools/qstringiterator_p.h
+++ b/src/corelib/tools/qstringiterator_p.h
@@ -71,6 +71,11 @@ public:
return pos;
}
+ inline int index() const
+ {
+ return pos - i;
+ }
+
inline void setPosition(QString::const_iterator position)
{
Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index af0ed228bd..adda91b739 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -57,6 +57,7 @@ HEADERS += \
tools/qsize.h \
tools/qstack.h \
tools/qstring.h \
+ tools/qstringalgorithms_p.h \
tools/qstringbuilder.h \
tools/qstringiterator_p.h \
tools/qstringlist.h \