Skip to content
Permalink
Browse files
Introduce new makeStringByReplacingAll(StringView, UChar, UChar) func…
…tion

https://bugs.webkit.org/show_bug.cgi?id=239728

Reviewed by Darin Adler.

Introduce new makeStringByReplacingAll(StringView, UChar, UChar) function, to complement
the existing makeStringByReplacingAll(const String&, UChar, UChar). This allows several
call sites to avoid a temporary String constructing since they have a StringView.

* Source/WebCore/PAL/pal/text/TextCodecICU.cpp:
(PAL::TextCodecICU::encode const):
* Source/WTF/wtf/URLParser.cpp:
(WTF::URLParser::parseURLEncodedForm):
* Source/WTF/wtf/text/StringImpl.cpp:
(WTF::StringImpl::replace):
* Source/WTF/wtf/text/StringImpl.h:
(WTF::StringImpl::createByReplacingInCharacters):
* Source/WTF/wtf/text/StringView.cpp:
(WTF::makeStringByReplacingAll):
* Source/WTF/wtf/text/StringView.h:
* Source/WebCore/Modules/plugins/YouTubePluginReplacement.cpp:
(WebCore::queryKeysAndValues):
* Source/WebCore/editing/cocoa/HTMLConverter.mm:
(WebCore::editingAttributedString):

Canonical link: https://commits.webkit.org/249969@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@293379 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Apr 26, 2022
1 parent a544915 commit de513a8bc42df19e456b5d76fa628a8078656473
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 51 deletions.
@@ -2887,12 +2887,12 @@ auto URLParser::parseURLEncodedForm(StringView input) -> URLEncodedForm
for (StringView bytes : input.split('&')) {
auto equalIndex = bytes.find('=');
if (equalIndex == notFound) {
auto name = formURLDecode(makeStringByReplacingAll(bytes.toString(), '+', 0x20));
auto name = formURLDecode(makeStringByReplacingAll(bytes, '+', 0x20));
if (name)
output.append({ name.value(), emptyString() });
} else {
auto name = formURLDecode(makeStringByReplacingAll(bytes.left(equalIndex).toString(), '+', 0x20));
auto value = formURLDecode(makeStringByReplacingAll(bytes.substring(equalIndex + 1).toString(), '+', 0x20));
auto name = formURLDecode(makeStringByReplacingAll(bytes.left(equalIndex), '+', 0x20));
auto value = formURLDecode(makeStringByReplacingAll(bytes.substring(equalIndex + 1), '+', 0x20));
if (name && value)
output.append({ name.value(), value.value() });
}
@@ -200,6 +200,9 @@ template<typename CharacterType> inline Ref<StringImpl> StringImpl::createUninit
return constructInternal<CharacterType>(*string, length);
}

template Ref<StringImpl> StringImpl::createUninitializedInternalNonEmpty(unsigned length, LChar*& data);
template Ref<StringImpl> StringImpl::createUninitializedInternalNonEmpty(unsigned length, UChar*& data);

Ref<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data)
{
return createUninitializedInternal(length, data);
@@ -1092,61 +1095,30 @@ Ref<StringImpl> StringImpl::replace(UChar target, UChar replacement)
{
if (target == replacement)
return *this;
unsigned i;
for (i = 0; i != m_length; ++i) {
UChar character = is8Bit() ? m_data8[i] : m_data16[i];
if (character == target)
break;
}
if (i == m_length)
return *this;

if (is8Bit()) {
if (!isLatin1(target)) {
// Looking for a 16-bit character in an 8-bit string, so we're done.
return *this;
}

if (isLatin1(replacement)) {
LChar* data;
LChar oldChar = static_cast<LChar>(target);
LChar newChar = static_cast<LChar>(replacement);

auto newImpl = createUninitializedInternalNonEmpty(m_length, data);

for (i = 0; i != m_length; ++i) {
LChar character = m_data8[i];
if (character == oldChar)
character = newChar;
data[i] = character;
}
return newImpl;
}

UChar* data;
auto newImpl = createUninitializedInternalNonEmpty(m_length, data);

unsigned i;
for (i = 0; i != m_length; ++i) {
UChar character = m_data8[i];
if (character == target)
character = replacement;
data[i] = character;
if (static_cast<UChar>(m_data8[i]) == target)
break;
}

return newImpl;
if (i == m_length)
return *this;
return createByReplacingInCharacters(m_data8, m_length, target, replacement, i);
}

UChar* data;
auto newImpl = createUninitializedInternalNonEmpty(m_length, data);

copyCharacters(data, m_data16, i);
for (unsigned j = i; j != m_length; ++j) {
UChar character = m_data16[j];
if (character == target)
character = replacement;
data[j] = character;
unsigned i;
for (i = 0; i != m_length; ++i) {
if (m_data16[i] == target)
break;
}
return newImpl;
if (i == m_length)
return *this;
return createByReplacingInCharacters(m_data16, m_length, target, replacement, i);
}

Ref<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringView string)
@@ -259,6 +259,9 @@ class StringImpl : private StringImplShape {
WTF_EXPORT_PRIVATE static Ref<StringImpl> createUninitialized(unsigned length, UChar*&);
template<typename CharacterType> static RefPtr<StringImpl> tryCreateUninitialized(unsigned length, CharacterType*&);

static Ref<StringImpl> createByReplacingInCharacters(const LChar*, unsigned length, UChar target, UChar replacement, unsigned indexOfFirstTargetCharacter);
static Ref<StringImpl> createByReplacingInCharacters(const UChar*, unsigned length, UChar target, UChar replacement, unsigned indexOfFirstTargetCharacter);

static Ref<StringImpl> createStaticStringImpl(const char* characters, unsigned length)
{
ASSERT(charactersAreAllASCII(bitwise_cast<const LChar*>(characters), length));
@@ -1324,6 +1327,44 @@ inline Ref<StringImpl> StringImpl::removeCharacters(const Predicate& findMatch)
return removeCharactersImpl(characters16(), findMatch);
}

inline Ref<StringImpl> StringImpl::createByReplacingInCharacters(const LChar* characters, unsigned length, UChar target, UChar replacement, unsigned indexOfFirstTargetCharacter)
{
ASSERT(indexOfFirstTargetCharacter < length);
if (isLatin1(replacement)) {
LChar* data;
LChar oldChar = target;
LChar newChar = replacement;
auto newImpl = createUninitializedInternalNonEmpty(length, data);
memcpy(data, characters, indexOfFirstTargetCharacter);
for (unsigned i = indexOfFirstTargetCharacter; i != length; ++i) {
LChar character = characters[i];
data[i] = character == oldChar ? newChar : character;
}
return newImpl;
}

UChar* data;
auto newImpl = createUninitializedInternalNonEmpty(length, data);
for (unsigned i = 0; i != length; ++i) {
UChar character = characters[i];
data[i] = character == target ? replacement : character;
}
return newImpl;
}

inline Ref<StringImpl> StringImpl::createByReplacingInCharacters(const UChar* characters, unsigned length, UChar target, UChar replacement, unsigned indexOfFirstTargetCharacter)
{
ASSERT(indexOfFirstTargetCharacter < length);
UChar* data;
auto newImpl = createUninitializedInternalNonEmpty(length, data);
copyCharacters(data, characters, indexOfFirstTargetCharacter);
for (unsigned i = indexOfFirstTargetCharacter; i != length; ++i) {
UChar character = characters[i];
data[i] = character == target ? replacement : character;
}
return newImpl;
}

} // namespace WTF

using WTF::StaticStringImpl;
@@ -386,6 +386,38 @@ size_t StringView::reverseFind(StringView matchString, unsigned start) const
return reverseFindInner(characters16(), matchString.characters16(), start, ourLength, matchLength);
}

String makeStringByReplacingAll(StringView string, UChar target, UChar replacement)
{
if (string.is8Bit()) {
if (!isLatin1(target)) {
// Looking for a 16-bit character in an 8-bit string, so we're done.
return string.toString();
}

auto* characters = string.characters8();
unsigned i;
unsigned length = string.length();
for (i = 0; i != length; ++i) {
if (characters[i] == target)
break;
}
if (i == length)
return string.toString();
return StringImpl::createByReplacingInCharacters(characters, length, target, replacement, i);
}

auto* characters = string.characters16();
unsigned i;
unsigned length = string.length();
for (i = 0; i != length; ++i) {
if (characters[i] == target)
break;
}
if (i == length)
return string.toString();
return StringImpl::createByReplacingInCharacters(characters, length, target, replacement, i);
}

int codePointCompare(StringView lhs, StringView rhs)
{
bool lhsIs8Bit = lhs.is8Bit();
@@ -1329,6 +1329,8 @@ inline String WARN_UNUSED_RETURN makeStringByReplacingAll(const String& string,
return string;
}

WTF_EXPORT_PRIVATE String WARN_UNUSED_RETURN makeStringByReplacingAll(StringView, UChar target, UChar replacement);

inline String WARN_UNUSED_RETURN makeStringBySimplifyingNewLines(const String& string)
{
return makeStringByReplacingAll(makeStringByReplacingAll(string, "\r\n"_s, "\n"_s), '\r', '\n');
@@ -148,8 +148,7 @@ static HashMap<String, String> queryKeysAndValues(StringView queryString)
// Save the key and the value.
if (keyLength && valueLength) {
String key = queryString.substring(keyLocation, keyLength).convertToASCIILowercase();
String value = queryString.substring(valueLocation, valueLength).toString();
value = makeStringByReplacingAll(value, '+', ' ');
auto value = makeStringByReplacingAll(queryString.substring(valueLocation, valueLength), '+', ' ');

if (!key.isEmpty() && !value.isEmpty())
queryDictionary.add(key, value);
@@ -302,7 +302,7 @@ Vector<uint8_t> TextCodecICU::encode(StringView string, UnencodableHandling hand
// Encoding will change the yen sign back into a backslash.
String copy;
if (shouldShowBackslashAsCurrencySymbolIn(m_encodingName)) {
copy = makeStringByReplacingAll(string.toStringWithoutCopying(), '\\', yenSign);
copy = makeStringByReplacingAll(string, '\\', yenSign);
string = copy;
}

@@ -2442,7 +2442,7 @@ AttributedString editingAttributedString(const SimpleRange& range, IncludeImages
if (style.nbspMode() == NBSPMode::Normal)
text = it.text().createNSStringWithoutCopying();
else
text = makeStringByReplacingAll(it.text().toString(), noBreakSpace, ' ');
text = makeStringByReplacingAll(it.text(), noBreakSpace, ' ');

[string replaceCharactersInRange:NSMakeRange(stringLength, 0) withString:text.get()];
[string setAttributes:attrs.get() range:NSMakeRange(stringLength, currentTextLength)];

0 comments on commit de513a8

Please sign in to comment.