QString: don't detach in remove(pos, len)
- If this string isn't shared, don't call detach, instead use ->erase() as needed - If this string is shared, create a new string, and copy all elements except the ones that would be removed, see task for details Update unittest to test both code paths. Task-number: QTBUG-106181 Change-Id: I4c73ff17a6fa89ddcf6966f9c5bf789753f6d39e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
dcfab7e28e
commit
f41089ba3d
@ -3294,9 +3294,22 @@ QString &QString::remove(qsizetype pos, qsizetype len)
|
|||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
len = std::min(len, size() - pos);
|
len = std::min(len, size() - pos);
|
||||||
detach();
|
|
||||||
d->erase(d.begin() + pos, len);
|
if (!d->isShared()) {
|
||||||
d.data()[d.size] = u'\0';
|
d->erase(d.begin() + pos, len);
|
||||||
|
d.data()[d.size] = u'\0';
|
||||||
|
} else {
|
||||||
|
// TODO: either reserve "size()", which is bigger than needed, or
|
||||||
|
// modify the shrinking-erase docs of this method (since the size
|
||||||
|
// of "copy" won't have any extra capacity any more)
|
||||||
|
const qsizetype sz = size() - len;
|
||||||
|
QString copy{sz, Qt::Uninitialized};
|
||||||
|
auto begin = d.begin();
|
||||||
|
auto toRemove_start = d.begin() + pos;
|
||||||
|
copy.d->copyRanges({{begin, toRemove_start},
|
||||||
|
{toRemove_start + len, d.end()}});
|
||||||
|
swap(copy);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +213,17 @@ public:
|
|||||||
--this->size;
|
--this->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Span { T *begin; T *end; };
|
||||||
|
|
||||||
|
void copyRanges(const std::initializer_list<Span> &ranges)
|
||||||
|
{
|
||||||
|
auto it = this->begin();
|
||||||
|
std::for_each(ranges.begin(), ranges.end(), [&it](const auto &span) {
|
||||||
|
it = std::copy(span.begin, span.end, it);
|
||||||
|
});
|
||||||
|
this->size = std::distance(this->begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
void assign(T *b, T *e, parameter_type t) noexcept
|
void assign(T *b, T *e, parameter_type t) noexcept
|
||||||
{
|
{
|
||||||
Q_ASSERT(b <= e);
|
Q_ASSERT(b <= e);
|
||||||
|
@ -3318,13 +3318,23 @@ void tst_QString::remove_uint_uint()
|
|||||||
QFETCH( int, index );
|
QFETCH( int, index );
|
||||||
QFETCH( int, len );
|
QFETCH( int, len );
|
||||||
QFETCH( QString, after );
|
QFETCH( QString, after );
|
||||||
|
QFETCH(QString, result);
|
||||||
|
|
||||||
if ( after.size() == 0 ) {
|
// For the replace() unitests?
|
||||||
QString s1 = string;
|
if ( after.size() != 0 ) {
|
||||||
s1.remove( (uint) index, (uint) len );
|
return;
|
||||||
QTEST( s1, "result" );
|
}
|
||||||
} else
|
|
||||||
QCOMPARE( 0, 0 ); // shut Qt Test
|
// Test when isShared() is true
|
||||||
|
QString s1 = string;
|
||||||
|
s1.remove((qsizetype)index, (qsizetype)len);
|
||||||
|
QCOMPARE(s1, result);
|
||||||
|
|
||||||
|
QString s2 = string;
|
||||||
|
// Test when isShared() is false
|
||||||
|
s2.detach();
|
||||||
|
s2.remove((qsizetype)index, (qsizetype)len);
|
||||||
|
QCOMPARE(s2, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QString::remove_string()
|
void tst_QString::remove_string()
|
||||||
|
Loading…
Reference in New Issue
Block a user