QString: don't detach in replace(QChar, QChar, case)

If the string is shared, instead of detaching, create a new string and
copy the characters from this string, replacing the ones matching "before"
with "after", to the new string.

Change-Id: I2c33690230d40f3121e60e242666460559258b7b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2022-11-20 14:49:04 +02:00
parent 482a75fef9
commit 26f8ea1224
2 changed files with 40 additions and 21 deletions

View File

@ -3793,27 +3793,39 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
*/
QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
{
if (d.size) {
const qsizetype idx = indexOf(before, 0, cs);
if (idx != -1) {
detach();
const char16_t a = after.unicode();
char16_t *i = d.data();
char16_t *const e = i + d.size;
i += idx;
*i = a;
++i;
if (cs == Qt::CaseSensitive) {
const char16_t toReplace = before.unicode();
std::replace(i, e, toReplace, a);
} else {
const char16_t toReplace = foldCase(before.unicode());
auto match = [toReplace](const char16_t c) {
return foldAndCompare(c, toReplace);
};
std::replace_if(i, e, match, a);
}
const qsizetype idx = indexOf(before, 0, cs);
if (idx == -1)
return *this;
const char16_t achar = after.unicode();
char16_t bchar = before.unicode();
auto matchesCIS = [](char16_t beforeChar) {
return [beforeChar](char16_t ch) { return foldAndCompare(ch, beforeChar); };
};
auto hit = d.begin() + idx;
if (!d.needsDetach()) {
*hit++ = achar;
if (cs == Qt::CaseSensitive) {
std::replace(hit, d.end(), bchar, achar);
} else {
bchar = foldCase(bchar);
std::replace_if(hit, d.end(), matchesCIS(bchar), achar);
}
} else {
QString other{ d.size, Qt::Uninitialized };
auto dest = std::copy(d.begin(), hit, other.d.begin());
*dest++ = achar;
++hit;
if (cs == Qt::CaseSensitive) {
std::replace_copy(hit, d.end(), dest, bchar, achar);
} else {
bchar = foldCase(bchar);
std::replace_copy_if(hit, d.end(), dest, matchesCIS(bchar), achar);
}
swap(other);
}
return *this;
}

View File

@ -764,7 +764,14 @@ void tst_QString::replace_qchar_qchar()
QFETCH(Qt::CaseSensitivity, cs);
QFETCH(QString, expected);
QCOMPARE(src.replace(before, after, cs), expected);
QString str = src;
// Test when string is shared
QCOMPARE(str.replace(before, after, cs), expected);
str = src;
// Test when it's not shared
str.detach();
QCOMPARE(str.replace(before, after, cs), expected);
}
void tst_QString::replace_qchar_qstring_data()