summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qstring.cpp')
-rw-r--r--src/corelib/tools/qstring.cpp515
1 files changed, 378 insertions, 137 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b623c62043..89d9889b2f 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -50,7 +50,6 @@
#include "qstringmatcher.h"
#include "qvarlengtharray.h"
#include "qtools_p.h"
-#include "qhash.h"
#include "qdebug.h"
#include "qendian.h"
#include "qcollator.h"
@@ -204,7 +203,7 @@ inline RetType UnrollTailLoop<0>::exec(int, RetType returnIfExited, Functor1, Fu
#endif
// conversion between Latin 1 and UTF-16
-void qt_from_latin1(ushort *dst, const char *str, size_t size)
+void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
{
/* SIMD:
* Unpacking with SSE has been shown to improve performance on recent CPUs
@@ -1201,6 +1200,22 @@ const QString::Null QString::null = { };
\sa QString::const_iterator
*/
+/*! \typedef QString::const_reverse_iterator
+ \since 5.6
+
+ This typedef provides an STL-style const reverse iterator for QString.
+
+ \sa QString::reverse_iterator, QString::const_iterator
+*/
+
+/*! \typedef QString::reverse_iterator
+ \since 5.6
+
+ This typedef provides an STL-style non-const reverse iterator for QString.
+
+ \sa QString::const_reverse_iterator, QString::iterator
+*/
+
/*!
\typedef QString::size_type
@@ -1304,6 +1319,52 @@ const QString::Null QString::null = { };
\sa constBegin(), end()
*/
+/*! \fn QString::reverse_iterator QString::rbegin()
+ \since 5.6
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ \sa begin(), crbegin(), rend()
+*/
+
+/*! \fn QString::const_reverse_iterator QString::rbegin() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QString::const_reverse_iterator QString::crbegin() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ \sa begin(), rbegin(), rend()
+*/
+
+/*! \fn QString::reverse_iterator QString::rend()
+ \since 5.6
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last character in the string, in reverse order.
+
+ \sa end(), crend(), rbegin()
+*/
+
+/*! \fn QString::const_reverse_iterator QString::rend() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QString::const_reverse_iterator QString::crend() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
+ past the last character in the string, in reverse order.
+
+ \sa end(), rend(), rbegin()
+*/
+
/*!
\fn QString::QString()
@@ -1448,7 +1509,7 @@ QString::QString(const QChar *unicode, int size)
} else {
if (size < 0) {
size = 0;
- while (unicode[size] != 0)
+ while (!unicode[size].isNull())
++size;
}
if (!size) {
@@ -1615,20 +1676,11 @@ void QString::resize(int size)
return;
}
- if (size == 0 && !d->capacityReserved) {
- Data *x = Data::allocate(0);
- if (!d->ref.deref())
- Data::deallocate(d);
- d = x;
- } else {
- if (d->ref.isShared() || uint(size) + 1u > d->alloc
- || (!d->capacityReserved && size < d->size
- && uint(size) + 1u < uint(d->alloc >> 1)))
- reallocData(uint(size) + 1u, true);
- if (d->alloc) {
- d->size = size;
- d->data()[size] = '\0';
- }
+ if (d->ref.isShared() || uint(size) + 1u > d->alloc)
+ reallocData(uint(size) + 1u, true);
+ if (d->alloc) {
+ d->size = size;
+ d->data()[size] = '\0';
}
}
@@ -1757,6 +1809,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
Assigns the Latin-1 string \a str to this string.
*/
+QString &QString::operator=(QLatin1String other)
+{
+ if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ d->size = other.size();
+ d->data()[other.size()] = 0;
+ qt_from_latin1(d->data(), other.latin1(), other.size());
+ } else {
+ *this = fromLatin1(other.latin1(), other.size());
+ }
+ return *this;
+}
/*! \fn QString &QString::operator=(const QByteArray &ba)
@@ -1807,7 +1870,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
*/
QString &QString::operator=(QChar ch)
{
- return operator=(QString(ch));
+ if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ // re-use existing capacity:
+ ushort *dat = d->data();
+ dat[0] = ch.unicode();
+ dat[1] = 0;
+ d->size = 1;
+ } else {
+ operator=(QString(ch));
+ }
+ return *this;
}
/*!
@@ -1828,6 +1900,51 @@ QString &QString::operator=(QChar ch)
/*!
+ \fn QString& QString::insert(int position, const QStringRef &str)
+ \since 5.5
+ \overload insert()
+
+ Inserts the string reference \a str at the given index \a position and
+ returns a reference to this string.
+
+ If the given \a position is greater than size(), the array is
+ first extended using resize().
+*/
+
+
+/*!
+ \fn QString& QString::insert(int position, const char *str)
+ \since 5.5
+ \overload insert()
+
+ Inserts the C string \a str at the given index \a position and
+ returns a reference to this string.
+
+ If the given \a position is greater than size(), the array is
+ first extended using resize().
+
+ This function is not available when QT_NO_CAST_FROM_ASCII is
+ defined.
+*/
+
+
+/*!
+ \fn QString& QString::insert(int position, const QByteArray &str)
+ \since 5.5
+ \overload insert()
+
+ Inserts the byte array \a str at the given index \a position and
+ returns a reference to this string.
+
+ If the given \a position is greater than size(), the array is
+ first extended using resize().
+
+ This function is not available when QT_NO_CAST_FROM_ASCII is
+ defined.
+*/
+
+
+/*!
\fn QString &QString::insert(int position, QLatin1String str)
\overload insert()
@@ -2027,6 +2144,22 @@ QString &QString::append(QChar ch)
Prepends the Latin-1 string \a str to this string.
*/
+/*! \fn QString &QString::prepend(const QChar *str, int len)
+ \since 5.5
+ \overload prepend()
+
+ Prepends \a len characters from the QChar array \a str to this string and
+ returns a reference to this string.
+*/
+
+/*! \fn QString &QString::prepend(const QStringRef &str)
+ \since 5.5
+ \overload prepend()
+
+ Prepends the string reference \a str to the beginning of this string and
+ returns a reference to this string.
+*/
+
/*! \fn QString &QString::prepend(const QByteArray &ba)
\overload prepend()
@@ -2558,6 +2691,8 @@ bool operator==(const QString &s1, const QString &s2)
/*!
\overload operator==()
+ Returns \c true if this string is equal to \a other; otherwise
+ returns \c false.
*/
bool QString::operator==(QLatin1String other) const
{
@@ -2616,7 +2751,7 @@ bool operator<(const QString &s1, const QString &s2)
}
/*!
\overload operator<()
- \relates QString
+
Returns \c true if this string is lexically less than the parameter
string called \a other; otherwise returns \c false.
*/
@@ -2659,9 +2794,9 @@ bool QString::operator<(QLatin1String other) const
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator<=(const QString &s1, const QString &s2)
+/*! \fn bool operator<=(const QString &s1, const QString &s2)
- \relates Qstring
+ \relates QString
Returns \c true if string \a s1 is lexically less than or equal to
string \a s2; otherwise returns \c false.
@@ -2707,7 +2842,7 @@ bool QString::operator<(QLatin1String other) const
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator>(const QString &s1, const QString &s2)
+/*! \fn bool operator>(const QString &s1, const QString &s2)
\relates QString
Returns \c true if string \a s1 is lexically greater than string \a s2;
@@ -2721,7 +2856,7 @@ bool QString::operator<(QLatin1String other) const
/*!
\overload operator>()
- \relates QString
+
Returns \c true if this string is lexically greater than the parameter
string \a other; otherwise returns \c false.
*/
@@ -3184,6 +3319,7 @@ struct QStringCapture
int len;
int no;
};
+Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE);
#endif
#ifndef QT_NO_REGEXP
@@ -3491,9 +3627,14 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const
}
/*!
- \overload count()
+ \overload count()
+
+ Returns the number of occurrences of character \a ch in the string.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
- Returns the number of occurrences of character \a ch in the string.
+ \sa contains(), indexOf()
*/
int QString::count(QChar ch, Qt::CaseSensitivity cs) const
@@ -3716,7 +3857,7 @@ int QString::indexOf(const QRegularExpression& re, int from) const
Example:
- \snippet qstring/main.cpp 97
+ \snippet qstring/main.cpp 99
*/
int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
{
@@ -3767,7 +3908,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const
Example:
- \snippet qstring/main.cpp 98
+ \snippet qstring/main.cpp 100
*/
int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
{
@@ -3939,10 +4080,9 @@ int QString::count(const QRegularExpression &re) const
QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const
{
- QStringList sections = split(sep, KeepEmptyParts,
- (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
+ const QVector<QStringRef> sections = splitRef(sep, KeepEmptyParts,
+ (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
const int sectionsSize = sections.size();
-
if (!(flags & SectionSkipEmpty)) {
if (start < 0)
start += sectionsSize;
@@ -3962,11 +4102,10 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
if (start >= sectionsSize || end < 0 || start > end)
return QString();
- int x = 0;
QString ret;
int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sectionsSize; ++i) {
- QString section = sections.at(i);
+ for (int x = 0, i = 0; x <= end && i < sectionsSize; ++i) {
+ const QStringRef &section = sections.at(i);
const bool empty = section.isEmpty();
if (x >= start) {
if(x == start)
@@ -3991,9 +4130,9 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
class qt_section_chunk {
public:
qt_section_chunk() {}
- qt_section_chunk(int l, QString s) : length(l), string(qMove(s)) {}
+ qt_section_chunk(int l, QStringRef s) : length(l), string(qMove(s)) {}
int length;
- QString string;
+ QStringRef string;
};
Q_DECLARE_TYPEINFO(qt_section_chunk, Q_MOVABLE_TYPE);
@@ -4086,12 +4225,12 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
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)));
+ 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, QString(uc + last_m, n - last_m)));
+ sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m)));
return extractSections(sections, start, end, flags);
}
@@ -4134,11 +4273,11 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
m = match.capturedStart();
- sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
+ sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, m - last_m)));
last_m = m;
last_len = match.capturedLength();
}
- sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
+ sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m)));
return extractSections(sections, start, end, flags);
}
@@ -4149,8 +4288,8 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
Returns a substring that contains the \a n leftmost characters
of the string.
- The entire string is returned if \a n is greater than size() or
- less than zero.
+ The entire string is returned if \a n is greater than or equal
+ to size(), or less than zero.
\snippet qstring/main.cpp 31
@@ -4167,8 +4306,8 @@ QString QString::left(int n) const
Returns a substring that contains the \a n rightmost characters
of the string.
- The entire string is returned if \a n is greater than size() or
- less than zero.
+ The entire string is returned if \a n is greater than or equal
+ to size(), or less than zero.
\snippet qstring/main.cpp 48
@@ -4822,7 +4961,7 @@ modifiable reference.
If \a position is negative, it is equivalent to passing zero.
- \sa chop(), resize(), left()
+ \sa chop(), resize(), left(), QStringRef::truncate()
*/
void QString::truncate(int pos)
@@ -4835,7 +4974,8 @@ void QString::truncate(int pos)
/*!
Removes \a n characters from the end of the string.
- If \a n is greater than size(), the result is an empty string.
+ If \a n is greater than or equal to size(), the result is an
+ empty string.
Example:
\snippet qstring/main.cpp 15
@@ -5537,34 +5677,36 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
*/
namespace QUnicodeTables {
-struct LowercaseTraits
-{
- static signed short caseDiff(const Properties *prop)
- { return prop->lowerCaseDiff; }
- static bool caseSpecial(const Properties *prop)
- { return prop->lowerCaseSpecial; }
-};
-
-struct UppercaseTraits
-{
- static signed short caseDiff(const Properties *prop)
- { return prop->upperCaseDiff; }
- static bool caseSpecial(const Properties *prop)
- { return prop->upperCaseSpecial; }
-};
+/*
+ \internal
+ Converts the \a str string starting from the position pointed to by the \a
+ it iterator, using the Unicode case traits \c Traits, and returns the
+ result. The input string must not be empty (the convertCase function below
+ guarantees that).
+
+ The string type \c{T} is also a template and is either \c{const QString} or
+ \c{QString}. This function can do both copy-conversion and in-place
+ conversion depending on the state of the \a str parameter:
+ \list
+ \li \c{T} is \c{const QString}: copy-convert
+ \li \c{T} is \c{QString} and its refcount != 1: copy-convert
+ \li \c{T} is \c{QString} and its refcount == 1: in-place convert
+ \endlist
-struct CasefoldTraits
-{
- static signed short caseDiff(const Properties *prop)
- { return prop->caseFoldDiff; }
- static bool caseSpecial(const Properties *prop)
- { return prop->caseFoldSpecial; }
-};
+ In copy-convert mode, the local variable \c{s} is detached from the input
+ \a str. In the in-place convert mode, \a str is in moved-from state (which
+ this function requires to be a valid, empty string) and \c{s} contains the
+ only copy of the string, without reallocation (thus, \a it is still valid).
+ There's one pathological case left: when the in-place conversion needs to
+ reallocate memory to grow the buffer. In that case, we need to adjust the \a
+ it pointer.
+ */
template <typename Traits, typename T>
Q_NEVER_INLINE
static QString detachAndConvertCase(T &str, QStringIterator it)
{
+ Q_ASSERT(!str.isEmpty());
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();
@@ -5573,12 +5715,19 @@ static QString detachAndConvertCase(T &str, QStringIterator it)
signed short caseDiff = Traits::caseDiff(prop);
if (Q_UNLIKELY(Traits::caseSpecial(prop))) {
- // slow path
+ // slow path: the string is growing
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;
+ int inpos = it.index() - 1;
+ int outpos = pp - s.constBegin();
+
+ s.replace(outpos, 1, reinterpret_cast<const QChar *>(specialCase), length);
+ pp = const_cast<QChar *>(s.constBegin()) + outpos + length;
+
+ // do we need to adjust the input iterator too?
+ // if it is pointing to s's data, str is empty
+ if (str.isEmpty())
+ it = QStringIterator(s.constBegin(), inpos + length, s.constEnd());
} else if (QChar::requiresSurrogates(uc)) {
*pp++ = QChar::highSurrogate(uc + caseDiff);
*pp++ = QChar::lowSurrogate(uc + caseDiff);
@@ -7622,86 +7771,155 @@ static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999)
return -1;
}
+/*
+ Algorithm for multiArg:
+
+ 1. Parse the string as a sequence of verbatim text and placeholders (%L?\d{,3}).
+ The L is parsed and accepted for compatibility with non-multi-arg, but since
+ multiArg only accepts strings as replacements, the localization request can
+ be safely ignored.
+ 2. The result of step (1) is a list of (string-ref,int)-tuples. The string-ref
+ either points at text to be copied verbatim (in which case the int is -1),
+ or, initially, at the textual representation of the placeholder. In that case,
+ the int contains the numerical number as parsed from the placeholder.
+ 3. Next, collect all the non-negative ints found, sort them in ascending order and
+ remove duplicates.
+ 3a. If the result has more entires than multiArg() was given replacement strings,
+ we have found placeholders we can't satisfy with replacement strings. That is
+ fine (there could be another .arg() call coming after this one), so just
+ truncate the result to the number of actual multiArg() replacement strings.
+ 3b. If the result has less entries than multiArg() was given replacement strings,
+ the string is missing placeholders. This is an error that the user should be
+ warned about.
+ 4. The result of step (3) is a mapping from the index of any replacement string to
+ placeholder number. This is the wrong way around, but since placeholder
+ numbers could get as large as 999, while we typically don't have more than 9
+ replacement strings, we trade 4K of sparsely-used memory for doing a reverse lookup
+ each time we need to map a placeholder number to a replacement string index
+ (that's a linear search; but still *much* faster than using an associative container).
+ 5. Next, for each of the tuples found in step (1), do the following:
+ 5a. If the int is negative, do nothing.
+ 5b. Otherwise, if the int is found in the result of step (3) at index I, replace
+ the string-ref with a string-ref for the (complete) I'th replacement string.
+ 5c. Otherwise, do nothing.
+ 6. Concatenate all string refs into a single result string.
+*/
+
namespace {
-class ArgMapper {
- QVarLengthArray<int, 16> argPosToNumberMap; // maps from argument position to number
-public:
- void found(int n) { argPosToNumberMap.push_back(n); }
+struct Part
+{
+ Part() : stringRef(), number(0) {}
+ Part(const QString &s, int pos, int len, int num = -1) Q_DECL_NOTHROW
+ : stringRef(&s, pos, len), number(num) {}
- struct AssignmentResult {
- int numArgs;
- int lastNumber;
- };
+ QStringRef stringRef;
+ int number;
+};
+} // unnamed namespace
- AssignmentResult assignArgumentNumberToEachOfTheNs(int numArgs)
- {
- std::sort(argPosToNumberMap.begin(), argPosToNumberMap.end());
- argPosToNumberMap.erase(std::unique(argPosToNumberMap.begin(), argPosToNumberMap.end()),
- argPosToNumberMap.end());
+template <>
+class QTypeInfo<Part> : public QTypeInfoMerger<Part, QStringRef, int> {}; // Q_DECLARE_METATYPE
- if (argPosToNumberMap.size() > numArgs)
- argPosToNumberMap.resize(numArgs);
- int lastNumber = argPosToNumberMap.empty() ? -1 : argPosToNumberMap.back();
- int arg = argPosToNumberMap.size();
+namespace {
- const AssignmentResult result = {arg, lastNumber};
- return result;
- }
+enum { ExpectedParts = 32 };
- int numberToArgsIndex(int number) const
- {
- if (number != -1) {
- const int * const it = std::find(argPosToNumberMap.begin(), argPosToNumberMap.end(), number);
- return it == argPosToNumberMap.end() ? -1 : it - argPosToNumberMap.begin();
- } else {
- return -1;
- }
- }
-};
-} // unnamed namespace
+typedef QVarLengthArray<Part, ExpectedParts> ParseResult;
+typedef QVarLengthArray<int, ExpectedParts/2> ArgIndexToPlaceholderMap;
-QString QString::multiArg(int numArgs, const QString **args) const
+static ParseResult parseMultiArgFormatString(const QString &s)
{
- QString result;
- ArgMapper mapper;
- const QChar *uc = (const QChar *) d->data();
- const int len = d->size;
+ ParseResult result;
+
+ const QChar *uc = s.constData();
+ const int len = s.size();
const int end = len - 1;
int i = 0;
+ int last = 0;
- // populate the arg-mapper with the %n's that actually occur in the string
while (i < end) {
if (uc[i] == QLatin1Char('%')) {
+ int percent = i;
int number = getEscape(uc, &i, len);
if (number != -1) {
- mapper.found(number);
+ if (last != percent)
+ result.push_back(Part(s, last, percent - last)); // literal text (incl. failed placeholders)
+ result.push_back(Part(s, percent, i - percent, number)); // parsed placeholder
+ last = i;
continue;
}
}
++i;
}
- const ArgMapper::AssignmentResult r = mapper.assignArgumentNumberToEachOfTheNs(numArgs);
+ if (last < len)
+ result.push_back(Part(s, last, len - last)); // trailing literal text
+
+ return result;
+}
+
+static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &parts)
+{
+ ArgIndexToPlaceholderMap result;
- // sanity
- if (numArgs > r.numArgs) {
- qWarning("QString::arg: %d argument(s) missing in %s", numArgs - r.numArgs, toLocal8Bit().data());
- numArgs = r.numArgs;
+ for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) {
+ if (it->number >= 0)
+ result.push_back(it->number);
}
- i = 0;
- while (i < len) {
- if (uc[i] == QLatin1Char('%') && i != end) {
- int number = getEscape(uc, &i, len, r.lastNumber);
- int arg = mapper.numberToArgsIndex(number);
- if (number != -1 && arg != -1) {
- result += *args[arg];
- continue;
- }
+ std::sort(result.begin(), result.end());
+ result.erase(std::unique(result.begin(), result.end()),
+ result.end());
+
+ return result;
+}
+
+static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[])
+{
+ int totalSize = 0;
+ for (ParseResult::iterator pit = parts.begin(), end = parts.end(); pit != end; ++pit) {
+ if (pit->number != -1) {
+ const ArgIndexToPlaceholderMap::const_iterator ait
+ = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), pit->number);
+ if (ait != argIndexToPlaceholderMap.end())
+ pit->stringRef = QStringRef(args[ait - argIndexToPlaceholderMap.begin()]);
+ }
+ totalSize += pit->stringRef.size();
+ }
+ return totalSize;
+}
+
+} // unnamed namespace
+
+QString QString::multiArg(int numArgs, const QString **args) const
+{
+ // Step 1-2 above
+ ParseResult parts = parseMultiArgFormatString(*this);
+
+ // 3-4
+ ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts);
+
+ if (argIndexToPlaceholderMap.size() > numArgs) // 3a
+ argIndexToPlaceholderMap.resize(numArgs);
+ else if (argIndexToPlaceholderMap.size() < numArgs) // 3b
+ qWarning("QString::arg: %d argument(s) missing in %s",
+ numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data());
+
+ // 5
+ const int totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args);
+
+ // 6:
+ QString result(totalSize, Qt::Uninitialized);
+ QChar *out = result.data();
+
+ for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) {
+ if (const int sz = it->stringRef.size()) {
+ memcpy(out, it->stringRef.constData(), sz * sizeof(QChar));
+ out += sz;
}
- result += uc[i++];
}
+
return result;
}
@@ -8024,14 +8242,25 @@ QString &QString::setRawData(const QChar *unicode, int size)
\snippet code/src_corelib_tools_qstring.cpp 6
+ \note If the function you're calling with a QLatin1String
+ argument isn't actually overloaded to take QLatin1String, the
+ implicit conversion to QString will trigger a memory allocation,
+ which is usually what you want to avoid by using QLatin1String
+ in the first place. In those cases, using QStringLiteral may be
+ the better option.
+
\sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral}
*/
+/*! \fn QLatin1String::QLatin1String()
+ \since 5.6
+
+ Constructs a QLatin1String object that stores a nullptr.
+*/
+
/*! \fn QLatin1String::QLatin1String(const char *str)
- Constructs a QLatin1String object that stores \a str. Note that if
- \a str is 0, an empty string is created; this case is handled by
- QString.
+ Constructs a QLatin1String object that stores \a str.
The string data is \e not copied. The caller must be able to
guarantee that \a str will not be deleted or modified as long as
@@ -8043,8 +8272,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
/*! \fn QLatin1String::QLatin1String(const char *str, int size)
Constructs a QLatin1String object that stores \a str with \a size.
- Note that if \a str is 0, an empty string is created; this case
- is handled by QString.
The string data is \e not copied. The caller must be able to
guarantee that \a str will not be deleted or modified as long as
@@ -9125,8 +9352,8 @@ QString &QString::append(const QStringRef &str)
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.
+ If \a n is greater than or equal to size(), or less than zero,
+ a reference to the entire string is returned.
\sa right(), mid(), startsWith()
*/
@@ -9143,8 +9370,8 @@ QStringRef QStringRef::left(int n) const
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.
+ If \a n is greater than or equal to size(), or less than zero,
+ a reference to the entire string is returned.
\snippet qstring/main.cpp leftRef
@@ -9164,8 +9391,8 @@ QStringRef QString::leftRef(int n) const
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.
+ If \a n is greater than or equal to size(), or less than zero,
+ a reference to the entire string is returned.
\sa left(), mid(), endsWith()
*/
@@ -9182,8 +9409,8 @@ QStringRef QStringRef::right(int n) const
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.
+ If \a n is greater than or equal to size(), or less than zero,
+ a reference to the entire string is returned.
\snippet qstring/main.cpp rightRef
@@ -9268,6 +9495,20 @@ QStringRef QString::midRef(int position, int n) const
}
/*!
+ \fn void QStringRef::truncate(int position)
+ \since 5.6
+
+ Truncates the string at the given \a position index.
+
+ If the specified \a position index is beyond the end of the
+ string, nothing happens.
+
+ If \a position is negative, it is equivalent to passing zero.
+
+ \sa QString::truncate()
+*/
+
+/*!
\since 4.8
Returns the index position of the first occurrence of the string \a