| Index: src/string-builder.cc
|
| diff --git a/src/string-builder.cc b/src/string-builder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..38c3188a9bcd769a83124bb265d172c5eb7541d3
|
| --- /dev/null
|
| +++ b/src/string-builder.cc
|
| @@ -0,0 +1,111 @@
|
| +// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/string-builder.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +MaybeHandle<String> ReplacementStringBuilder::ToString() {
|
| + Isolate* isolate = heap_->isolate();
|
| + if (array_builder_.length() == 0) {
|
| + return isolate->factory()->empty_string();
|
| + }
|
| +
|
| + Handle<String> joined_string;
|
| + if (is_one_byte_) {
|
| + Handle<SeqOneByteString> seq;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, seq, isolate->factory()->NewRawOneByteString(character_count_),
|
| + String);
|
| +
|
| + DisallowHeapAllocation no_gc;
|
| + uint8_t* char_buffer = seq->GetChars();
|
| + StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
|
| + array_builder_.length());
|
| + joined_string = Handle<String>::cast(seq);
|
| + } else {
|
| + // Two-byte.
|
| + Handle<SeqTwoByteString> seq;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_),
|
| + String);
|
| +
|
| + DisallowHeapAllocation no_gc;
|
| + uc16* char_buffer = seq->GetChars();
|
| + StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
|
| + array_builder_.length());
|
| + joined_string = Handle<String>::cast(seq);
|
| + }
|
| + return joined_string;
|
| +}
|
| +
|
| +
|
| +IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate)
|
| + : isolate_(isolate),
|
| + encoding_(String::ONE_BYTE_ENCODING),
|
| + overflowed_(false),
|
| + part_length_(kInitialPartLength),
|
| + current_index_(0) {
|
| + // Create an accumulator handle starting with the empty string.
|
| + accumulator_ = Handle<String>(isolate->heap()->empty_string(), isolate);
|
| + current_part_ =
|
| + factory()->NewRawOneByteString(part_length_).ToHandleChecked();
|
| +}
|
| +
|
| +
|
| +void IncrementalStringBuilder::Accumulate() {
|
| + // Only accumulate fully written strings. Shrink first if necessary.
|
| + DCHECK_EQ(current_index_, current_part()->length());
|
| + Handle<String> new_accumulator;
|
| + if (accumulator()->length() + current_part()->length() > String::kMaxLength) {
|
| + // Set the flag and carry on. Delay throwing the exception till the end.
|
| + new_accumulator = factory()->empty_string();
|
| + overflowed_ = true;
|
| + } else {
|
| + new_accumulator = factory()
|
| + ->NewConsString(accumulator(), current_part())
|
| + .ToHandleChecked();
|
| + }
|
| + set_accumulator(new_accumulator);
|
| +}
|
| +
|
| +
|
| +void IncrementalStringBuilder::Extend() {
|
| + Accumulate();
|
| + if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
|
| + part_length_ *= kPartLengthGrowthFactor;
|
| + }
|
| + Handle<String> new_part;
|
| + if (encoding_ == String::ONE_BYTE_ENCODING) {
|
| + new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked();
|
| + } else {
|
| + new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked();
|
| + }
|
| + // Reuse the same handle to avoid being invalidated when exiting handle scope.
|
| + set_current_part(new_part);
|
| + current_index_ = 0;
|
| +}
|
| +
|
| +
|
| +MaybeHandle<String> IncrementalStringBuilder::Finish() {
|
| + ShrinkCurrentPart();
|
| + Accumulate();
|
| + if (overflowed_) {
|
| + THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String);
|
| + }
|
| + return accumulator();
|
| +}
|
| +
|
| +
|
| +void IncrementalStringBuilder::AppendString(Handle<String> string) {
|
| + ShrinkCurrentPart();
|
| + part_length_ = kInitialPartLength; // Allocate conservatively.
|
| + Extend(); // Attach current part and allocate new part.
|
| + Handle<String> concat =
|
| + factory()->NewConsString(accumulator(), string).ToHandleChecked();
|
| + set_accumulator(concat);
|
| +}
|
| +}
|
| +} // namespace v8::internal
|
|
|