blob: 6c5144d574aea64ea2ccc04fadf1afdc2e7d8999 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/string-builder.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/isolate-inl.h"
8#include "src/objects-inl.h"
9
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010namespace v8 {
11namespace internal {
12
13MaybeHandle<String> ReplacementStringBuilder::ToString() {
14 Isolate* isolate = heap_->isolate();
15 if (array_builder_.length() == 0) {
16 return isolate->factory()->empty_string();
17 }
18
19 Handle<String> joined_string;
20 if (is_one_byte_) {
21 Handle<SeqOneByteString> seq;
22 ASSIGN_RETURN_ON_EXCEPTION(
23 isolate, seq, isolate->factory()->NewRawOneByteString(character_count_),
24 String);
25
26 DisallowHeapAllocation no_gc;
27 uint8_t* char_buffer = seq->GetChars();
28 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
29 array_builder_.length());
30 joined_string = Handle<String>::cast(seq);
31 } else {
32 // Two-byte.
33 Handle<SeqTwoByteString> seq;
34 ASSIGN_RETURN_ON_EXCEPTION(
35 isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_),
36 String);
37
38 DisallowHeapAllocation no_gc;
39 uc16* char_buffer = seq->GetChars();
40 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
41 array_builder_.length());
42 joined_string = Handle<String>::cast(seq);
43 }
44 return joined_string;
45}
46
47
48IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate)
49 : isolate_(isolate),
50 encoding_(String::ONE_BYTE_ENCODING),
51 overflowed_(false),
52 part_length_(kInitialPartLength),
53 current_index_(0) {
54 // Create an accumulator handle starting with the empty string.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 accumulator_ = Handle<String>::New(isolate->heap()->empty_string(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 current_part_ =
57 factory()->NewRawOneByteString(part_length_).ToHandleChecked();
58}
59
60
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061void IncrementalStringBuilder::Accumulate(Handle<String> new_part) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062 Handle<String> new_accumulator;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 if (accumulator()->length() + new_part->length() > String::kMaxLength) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064 // Set the flag and carry on. Delay throwing the exception till the end.
65 new_accumulator = factory()->empty_string();
66 overflowed_ = true;
67 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 new_accumulator =
69 factory()->NewConsString(accumulator(), new_part).ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040070 }
71 set_accumulator(new_accumulator);
72}
73
74
75void IncrementalStringBuilder::Extend() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 DCHECK_EQ(current_index_, current_part()->length());
77 Accumulate(current_part());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
79 part_length_ *= kPartLengthGrowthFactor;
80 }
81 Handle<String> new_part;
82 if (encoding_ == String::ONE_BYTE_ENCODING) {
83 new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked();
84 } else {
85 new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked();
86 }
87 // Reuse the same handle to avoid being invalidated when exiting handle scope.
88 set_current_part(new_part);
89 current_index_ = 0;
90}
91
92
93MaybeHandle<String> IncrementalStringBuilder::Finish() {
94 ShrinkCurrentPart();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 Accumulate(current_part());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 if (overflowed_) {
97 THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String);
98 }
99 return accumulator();
100}
101
102
103void IncrementalStringBuilder::AppendString(Handle<String> string) {
104 ShrinkCurrentPart();
105 part_length_ = kInitialPartLength; // Allocate conservatively.
106 Extend(); // Attach current part and allocate new part.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 Accumulate(string);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109} // namespace internal
110} // namespace v8