blob: 77ddfe1642a076d43a23a16bcff8d486a4482f7e [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
namespace blink {
namespace {
// Caution: This function calls `Clear()` for items in `pieces` even though
// the items are `const`, in order to pass checks in ~StringView().
String StrCat(base::span<const StringView> pieces) {
size_t size = 0;
bool is_8bit = true;
for (const auto& view : pieces) {
size += view.length();
if (is_8bit && !view.Is8Bit()) {
// Like StringBuilder, we check one-length 16bit strings.
is_8bit = view.length() == 1 && view[0] < 0x0100;
}
}
if (is_8bit) {
base::span<LChar> buffer;
auto impl = StringImpl::CreateUninitialized(size, buffer);
for (const auto& view : pieces) {
base::span<LChar> sub_buffer = buffer.take_first(view.length());
if (view.Is8Bit()) {
sub_buffer.copy_from(view.Span8());
} else {
DCHECK_EQ(sub_buffer.size(), 1u);
DCHECK_LT(view[0], 0x0100);
sub_buffer[0] = view[0];
}
#if DCHECK_IS_ON()
const_cast<StringView&>(view).Clear();
#endif
}
return impl;
}
base::span<UChar> buffer;
auto impl = StringImpl::CreateUninitialized(size, buffer);
for (const auto& view : pieces) {
base::span<UChar> sub_buffer = buffer.take_first(view.length());
if (view.Is8Bit()) {
std::ranges::copy(view.Span8(), sub_buffer.begin());
} else {
sub_buffer.copy_from(view.Span16());
}
#if DCHECK_IS_ON()
const_cast<StringView&>(view).Clear();
#endif
}
return impl;
}
} // namespace
String StrCat(std::initializer_list<StringView> pieces) {
return StrCat(base::span(pieces));
}
} // namespace blink