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;
|
||||
|
||||
len = std::min(len, size() - pos);
|
||||
detach();
|
||||
d->erase(d.begin() + pos, len);
|
||||
d.data()[d.size] = u'\0';
|
||||
|
||||
if (!d->isShared()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,17 @@ public:
|
||||
--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
|
||||
{
|
||||
Q_ASSERT(b <= e);
|
||||
|
@ -3318,13 +3318,23 @@ void tst_QString::remove_uint_uint()
|
||||
QFETCH( int, index );
|
||||
QFETCH( int, len );
|
||||
QFETCH( QString, after );
|
||||
QFETCH(QString, result);
|
||||
|
||||
if ( after.size() == 0 ) {
|
||||
QString s1 = string;
|
||||
s1.remove( (uint) index, (uint) len );
|
||||
QTEST( s1, "result" );
|
||||
} else
|
||||
QCOMPARE( 0, 0 ); // shut Qt Test
|
||||
// For the replace() unitests?
|
||||
if ( after.size() != 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
Loading…
Reference in New Issue
Block a user