Remove '\0' space reservation logic in QByteArray
Changed QByteArray to use implicit element reserved by QArrayData Task-number: QTBUG-84320 Change-Id: I2a0091c814a47a5c052da7a83d10cb641834c7bd Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
7249a87b06
commit
04d78df344
@ -642,7 +642,7 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes)
|
|||||||
return invalidCompressedData();
|
return invalidCompressedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray::DataPointer d(QByteArray::Data::allocate(expectedSize + 1));
|
QByteArray::DataPointer d(QByteArray::Data::allocate(len));
|
||||||
if (Q_UNLIKELY(d.data() == nullptr))
|
if (Q_UNLIKELY(d.data() == nullptr))
|
||||||
return invalidCompressedData();
|
return invalidCompressedData();
|
||||||
|
|
||||||
@ -1149,12 +1149,11 @@ QByteArray &QByteArray::operator=(const char *str)
|
|||||||
d = DataPointer::fromRawData(&_empty, 0);
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
} else {
|
} else {
|
||||||
const qsizetype len = qsizetype(strlen(str));
|
const qsizetype len = qsizetype(strlen(str));
|
||||||
const size_t fullLen = size_t(len) + 1;
|
|
||||||
const auto capacityAtEnd = d->allocatedCapacity() - d.freeSpaceAtBegin();
|
const auto capacityAtEnd = d->allocatedCapacity() - d.freeSpaceAtBegin();
|
||||||
if (d->needsDetach() || fullLen > capacityAtEnd
|
if (d->needsDetach() || size_t(len) > capacityAtEnd
|
||||||
|| (len < size() && fullLen < (capacityAtEnd >> 1)))
|
|| (len < size() && size_t(len) < (capacityAtEnd >> 1)))
|
||||||
reallocData(fullLen, d->detachFlags());
|
reallocData(len, d->detachFlags());
|
||||||
memcpy(d.data(), str, fullLen); // include null terminator
|
memcpy(d.data(), str, len + 1); // include null terminator
|
||||||
d.size = len;
|
d.size = len;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -1582,10 +1581,14 @@ QByteArray::QByteArray(const char *data, qsizetype size)
|
|||||||
d = DataPointer();
|
d = DataPointer();
|
||||||
} else {
|
} else {
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
size = int(strlen(data));
|
size = qstrlen(data);
|
||||||
d = DataPointer(Data::allocate(size + 1u), size);
|
if (!size) {
|
||||||
memcpy(d.data(), data, size);
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
d.data()[size] = '\0';
|
} else {
|
||||||
|
d = DataPointer(Data::allocate(size), size);
|
||||||
|
memcpy(d.data(), data, size);
|
||||||
|
d.data()[size] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1600,7 +1603,7 @@ QByteArray::QByteArray(qsizetype size, char ch)
|
|||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
d = DataPointer::fromRawData(&_empty, 0);
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
} else {
|
} else {
|
||||||
d = DataPointer(Data::allocate(size + 1u), size);
|
d = DataPointer(Data::allocate(size), size);
|
||||||
memset(d.data(), ch, size);
|
memset(d.data(), ch, size);
|
||||||
d.data()[size] = '\0';
|
d.data()[size] = '\0';
|
||||||
}
|
}
|
||||||
@ -1614,8 +1617,12 @@ QByteArray::QByteArray(qsizetype size, char ch)
|
|||||||
|
|
||||||
QByteArray::QByteArray(qsizetype size, Qt::Initialization)
|
QByteArray::QByteArray(qsizetype size, Qt::Initialization)
|
||||||
{
|
{
|
||||||
d = DataPointer(Data::allocate(size + 1u), size);
|
if (size <= 0) {
|
||||||
d.data()[size] = '\0';
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
|
} else {
|
||||||
|
d = DataPointer(Data::allocate(size), size);
|
||||||
|
d.data()[size] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1637,7 +1644,7 @@ void QByteArray::resize(qsizetype size)
|
|||||||
|
|
||||||
const auto capacityAtEnd = capacity() - d.freeSpaceAtBegin();
|
const auto capacityAtEnd = capacity() - d.freeSpaceAtBegin();
|
||||||
if (d->needsDetach() || size > capacityAtEnd)
|
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;
|
d.size = size;
|
||||||
if (d->allocatedCapacity())
|
if (d->allocatedCapacity())
|
||||||
d.data()[size] = 0;
|
d.data()[size] = 0;
|
||||||
@ -1663,13 +1670,18 @@ QByteArray &QByteArray::fill(char ch, qsizetype size)
|
|||||||
|
|
||||||
void QByteArray::reallocData(size_t alloc, Data::ArrayOptions options)
|
void QByteArray::reallocData(size_t alloc, Data::ArrayOptions options)
|
||||||
{
|
{
|
||||||
|
if (!alloc) {
|
||||||
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// there's a case of slow reallocate path where we need to memmove the data
|
// 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"
|
// before a call to ::realloc(), meaning that there's an extra "heavy"
|
||||||
// operation. just prefer ::malloc() branch in this case
|
// operation. just prefer ::malloc() branch in this case
|
||||||
const bool slowReallocatePath = d.freeSpaceAtBegin() > 0;
|
const bool slowReallocatePath = d.freeSpaceAtBegin() > 0;
|
||||||
|
|
||||||
if (d->needsDetach() || slowReallocatePath) {
|
if (d->needsDetach() || slowReallocatePath) {
|
||||||
DataPointer dd(Data::allocate(alloc, options), qMin(qsizetype(alloc) - 1, d.size));
|
DataPointer dd(Data::allocate(alloc, options), qMin(qsizetype(alloc), d.size));
|
||||||
if (dd.size > 0)
|
if (dd.size > 0)
|
||||||
::memcpy(dd.data(), d.data(), dd.size);
|
::memcpy(dd.data(), d.data(), dd.size);
|
||||||
dd.data()[dd.size] = 0;
|
dd.data()[dd.size] = 0;
|
||||||
@ -1681,8 +1693,11 @@ void QByteArray::reallocData(size_t alloc, Data::ArrayOptions options)
|
|||||||
|
|
||||||
void QByteArray::reallocGrowData(size_t alloc, Data::ArrayOptions options)
|
void QByteArray::reallocGrowData(size_t alloc, Data::ArrayOptions options)
|
||||||
{
|
{
|
||||||
|
if (!alloc) // expected to always allocate
|
||||||
|
alloc = 1;
|
||||||
|
|
||||||
if (d->needsDetach()) {
|
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));
|
DataPointer dd(DataPointer::allocateGrow(d, alloc, newSize, options));
|
||||||
dd->copyAppend(d.data(), d.data() + newSize);
|
dd->copyAppend(d.data(), d.data() + newSize);
|
||||||
dd.data()[dd.size] = 0;
|
dd.data()[dd.size] = 0;
|
||||||
@ -1851,7 +1866,7 @@ QByteArray& QByteArray::append(char ch)
|
|||||||
{
|
{
|
||||||
const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), 1);
|
const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), 1);
|
||||||
if (d->needsDetach() || size() + 1 > capacity() || shouldGrow)
|
if (d->needsDetach() || size() + 1 > capacity() || shouldGrow)
|
||||||
reallocGrowData(size_t(size()) + 2u, d->detachFlags() | Data::GrowsForward);
|
reallocGrowData(size_t(size()) + 1u, d->detachFlags() | Data::GrowsForward);
|
||||||
d->copyAppend(1, ch);
|
d->copyAppend(1, ch);
|
||||||
d.data()[d.size] = '\0';
|
d.data()[d.size] = '\0';
|
||||||
return *this;
|
return *this;
|
||||||
@ -1888,7 +1903,7 @@ QByteArray &QByteArray::insert(qsizetype i, QByteArrayView data)
|
|||||||
auto flags = d->detachFlags() | Data::GrowsForward;
|
auto flags = d->detachFlags() | Data::GrowsForward;
|
||||||
if (oldSize != 0 && i <= oldSize / 4) // using QList's policy
|
if (oldSize != 0 && i <= oldSize / 4) // using QList's policy
|
||||||
flags |= Data::GrowsBackwards;
|
flags |= Data::GrowsBackwards;
|
||||||
reallocGrowData(newSize + 1, flags);
|
reallocGrowData(newSize, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > oldSize) // set spaces in the uninitialized gap
|
if (i > oldSize) // set spaces in the uninitialized gap
|
||||||
@ -1944,7 +1959,7 @@ QByteArray &QByteArray::insert(qsizetype i, qsizetype count, char ch)
|
|||||||
auto flags = d->detachFlags() | Data::GrowsForward;
|
auto flags = d->detachFlags() | Data::GrowsForward;
|
||||||
if (oldSize != 0 && i <= oldSize / 4) // using QList's policy
|
if (oldSize != 0 && i <= oldSize / 4) // using QList's policy
|
||||||
flags |= Data::GrowsBackwards;
|
flags |= Data::GrowsBackwards;
|
||||||
reallocGrowData(newSize + 1, flags);
|
reallocGrowData(newSize, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > oldSize) // set spaces in the uninitialized gap
|
if (i > oldSize) // set spaces in the uninitialized gap
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
** Copyright (C) 2016 Intel Corporation.
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
@ -513,19 +513,18 @@ inline const char *QByteArray::data() const
|
|||||||
inline const char *QByteArray::constData() const
|
inline const char *QByteArray::constData() const
|
||||||
{ return data(); }
|
{ return data(); }
|
||||||
inline void QByteArray::detach()
|
inline void QByteArray::detach()
|
||||||
{ if (d->needsDetach()) reallocData(size_t(size()) + 1u, d->detachFlags()); }
|
{ if (d->needsDetach()) reallocData(size_t(size()), d->detachFlags()); }
|
||||||
inline bool QByteArray::isDetached() const
|
inline bool QByteArray::isDetached() const
|
||||||
{ return !d->isShared(); }
|
{ return !d->isShared(); }
|
||||||
inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d)
|
inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline qsizetype QByteArray::capacity() const
|
inline qsizetype QByteArray::capacity() const { return qsizetype(d->constAllocatedCapacity()); }
|
||||||
{ const auto realCapacity = d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; }
|
|
||||||
|
|
||||||
inline void QByteArray::reserve(qsizetype asize)
|
inline void QByteArray::reserve(qsizetype asize)
|
||||||
{
|
{
|
||||||
if (d->needsDetach() || asize > capacity() - d->freeSpaceAtBegin()) {
|
if (d->needsDetach() || asize > capacity() - d->freeSpaceAtBegin()) {
|
||||||
reallocData(qMax(size_t(size()), size_t(asize)) + 1u, d->detachFlags() | Data::CapacityReserved);
|
reallocData(qMax(size_t(size()), size_t(asize)), d->detachFlags() | Data::CapacityReserved);
|
||||||
} else {
|
} else {
|
||||||
d->setFlag(Data::CapacityReserved);
|
d->setFlag(Data::CapacityReserved);
|
||||||
}
|
}
|
||||||
@ -536,7 +535,7 @@ inline void QByteArray::squeeze()
|
|||||||
if ((d->flags() & Data::CapacityReserved) == 0)
|
if ((d->flags() & Data::CapacityReserved) == 0)
|
||||||
return;
|
return;
|
||||||
if (d->needsDetach() || size() < capacity()) {
|
if (d->needsDetach() || size() < capacity()) {
|
||||||
reallocData(size_t(size()) + 1u, d->detachFlags() & ~Data::CapacityReserved);
|
reallocData(size_t(size()), d->detachFlags() & ~Data::CapacityReserved);
|
||||||
} else {
|
} else {
|
||||||
d->clearFlag(Data::CapacityReserved);
|
d->clearFlag(Data::CapacityReserved);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user