diff options
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r-- | src/corelib/text/qstring.cpp | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index dd1b57dbf3..263dd0f302 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2232,7 +2232,7 @@ QString::QString(const QChar *unicode, qsizetype size) if (!size) { d = DataPointer::fromRawData(&_empty, 0); } else { - d = DataPointer(Data::allocate(size + 1), size); + d = DataPointer(Data::allocate(size), size); memcpy(d.data(), unicode, size * sizeof(QChar)); d.data()[size] = '\0'; } @@ -2250,7 +2250,7 @@ QString::QString(qsizetype size, QChar ch) if (size <= 0) { d = DataPointer::fromRawData(&_empty, 0); } else { - d = DataPointer(Data::allocate(size + 1), size); + d = DataPointer(Data::allocate(size), size); d.data()[size] = '\0'; char16_t *i = d.data() + size; char16_t *b = d.data(); @@ -2268,8 +2268,12 @@ QString::QString(qsizetype size, QChar ch) */ QString::QString(qsizetype size, Qt::Initialization) { - d = DataPointer(Data::allocate(size + 1), size); - d.data()[size] = '\0'; + if (size <= 0) { + d = DataPointer::fromRawData(&_empty, 0); + } else { + d = DataPointer(Data::allocate(size), size); + d.data()[size] = '\0'; + } } /*! \fn QString::QString(QLatin1String str) @@ -2284,7 +2288,7 @@ QString::QString(qsizetype size, Qt::Initialization) */ QString::QString(QChar ch) { - d = DataPointer(Data::allocate(2), 1); + d = DataPointer(Data::allocate(1), 1); d.data()[0] = ch.unicode(); d.data()[1] = '\0'; } @@ -2380,7 +2384,7 @@ void QString::resize(qsizetype size) const auto capacityAtEnd = capacity() - d.freeSpaceAtBegin(); if (d->needsDetach() || size > capacityAtEnd) - reallocData(size_t(size) + 1u, d->detachFlags() | Data::GrowsForward); + reallocData(size_t(size), d->detachFlags() | Data::GrowsForward); d.size = size; if (d->allocatedCapacity()) d.data()[size] = 0; @@ -2460,13 +2464,18 @@ void QString::resize(qsizetype size, QChar fillChar) void QString::reallocData(size_t alloc, Data::ArrayOptions allocOptions) { + if (!alloc) { + d = DataPointer::fromRawData(&_empty, 0); + return; + } + // there's a case of slow reallocate path where we need to memmove the data // before a call to ::realloc(), meaning that there's an extra "heavy" // operation. just prefer ::malloc() branch in this case const bool slowReallocatePath = d.freeSpaceAtBegin() > 0; if (d->needsDetach() || slowReallocatePath) { - DataPointer dd(Data::allocate(alloc, allocOptions), qMin(qsizetype(alloc) - 1, d.size)); + DataPointer dd(Data::allocate(alloc, allocOptions), qMin(qsizetype(alloc), d.size)); if (dd.size > 0) ::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar)); dd.data()[dd.size] = 0; @@ -2478,8 +2487,11 @@ void QString::reallocData(size_t alloc, Data::ArrayOptions allocOptions) void QString::reallocGrowData(size_t alloc, Data::ArrayOptions options) { + if (!alloc) // expected to always allocate + alloc = 1; + if (d->needsDetach()) { - const auto newSize = qMin(qsizetype(alloc) - 1, d.size); + const auto newSize = qMin(qsizetype(alloc), d.size); DataPointer dd(DataPointer::allocateGrow(d, alloc, newSize, options)); dd->copyAppend(d.data(), d.data() + newSize); dd.data()[dd.size] = 0; @@ -2695,7 +2707,7 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size) // ### optimize me if (d->needsDetach() || newSize > capacity() || shouldGrow) - reallocGrowData(newSize + 1, flags); + reallocGrowData(newSize, flags); if (i > oldSize) // set spaces in the uninitialized gap d->copyAppend(i - oldSize, u' '); @@ -2729,7 +2741,7 @@ QString& QString::insert(qsizetype i, QChar ch) // ### optimize me if (d->needsDetach() || newSize > capacity() || shouldGrow) - reallocGrowData(newSize + 1, flags); + reallocGrowData(newSize, flags); if (i > oldSize) // set spaces in the uninitialized gap d->copyAppend(i - oldSize, u' '); @@ -2765,7 +2777,7 @@ QString &QString::append(const QString &str) } else { const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), str.d.size); if (d->needsDetach() || size() + str.size() > capacity() || shouldGrow) - reallocGrowData(uint(size() + str.size()) + 1u, + reallocGrowData(uint(size() + str.size()), d->detachFlags() | Data::GrowsForward); d->copyAppend(str.d.data(), str.d.data() + str.d.size); d.data()[d.size] = '\0'; @@ -2785,7 +2797,7 @@ QString &QString::append(const QChar *str, qsizetype len) if (str && len > 0) { const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), len); if (d->needsDetach() || size() + len > capacity() || shouldGrow) - reallocGrowData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward); + reallocGrowData(uint(size() + len), d->detachFlags() | Data::GrowsForward); static_assert(sizeof(QChar) == sizeof(char16_t), "Unexpected difference in sizes"); // the following should be safe as QChar uses char16_t as underlying data const char16_t *char16String = reinterpret_cast<const char16_t *>(str); @@ -2807,7 +2819,7 @@ QString &QString::append(QLatin1String str) qsizetype len = str.size(); const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), len); if (d->needsDetach() || size() + len > capacity() || shouldGrow) - reallocGrowData(size_t(size() + len) + 1u, d->detachFlags() | Data::GrowsForward); + reallocGrowData(size_t(size() + len), d->detachFlags() | Data::GrowsForward); if (d.freeSpaceAtBegin() == 0) { // fast path char16_t *i = d.data() + d.size; @@ -2860,7 +2872,7 @@ QString &QString::append(QChar ch) { const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), 1); if (d->needsDetach() || size() + 1 > capacity() || shouldGrow) - reallocGrowData(d.size + 2u, d->detachFlags() | Data::GrowsForward); + reallocGrowData(d.size + 1u, d->detachFlags() | Data::GrowsForward); d->copyAppend(1, ch.unicode()); d.data()[d.size] = '\0'; return *this; @@ -2963,8 +2975,9 @@ QString &QString::remove(qsizetype pos, qsizetype len) } else if (len > 0) { detach(); memmove(d.data() + pos, d.data() + pos + len, - (d.size - pos - len + 1) * sizeof(QChar)); + (d.size - pos - len) * sizeof(QChar)); d.size -= len; + d.data()[d.size] = '\0'; } return *this; } @@ -3998,7 +4011,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) if (!iterator.hasNext()) // no matches at all return *this; - reallocData(size_t(d.size) + 1u, d->detachFlags()); + reallocData(size_t(d.size), d->detachFlags()); qsizetype numCaptures = re.captureCount(); @@ -5105,10 +5118,9 @@ QString::DataPointer QString::fromLatin1_helper(const char *str, qsizetype size) } else { if (size < 0) size = qstrlen(str); - d = DataPointer(Data::allocate(size + 1), size); + d = DataPointer(Data::allocate(size), size); d.data()[size] = '\0'; char16_t *dst = d.data(); - qt_from_latin1(dst, str, size_t(size)); } return d; @@ -6089,7 +6101,7 @@ const ushort *QString::utf16() const { if (!d->isMutable()) { // ensure '\0'-termination for ::fromRawData strings - const_cast<QString*>(this)->reallocData(size_t(d.size) + 1u, d->detachFlags()); + const_cast<QString*>(this)->reallocData(size_t(d.size), d->detachFlags()); } return reinterpret_cast<const ushort *>(d.data()); } |