OLD | NEW |
(Empty) | |
| 1 // 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 |
| 7 namespace v8 { |
| 8 namespace internal { |
| 9 |
| 10 MaybeHandle<String> ReplacementStringBuilder::ToString() { |
| 11 Isolate* isolate = heap_->isolate(); |
| 12 if (array_builder_.length() == 0) { |
| 13 return isolate->factory()->empty_string(); |
| 14 } |
| 15 |
| 16 Handle<String> joined_string; |
| 17 if (is_one_byte_) { |
| 18 Handle<SeqOneByteString> seq; |
| 19 ASSIGN_RETURN_ON_EXCEPTION( |
| 20 isolate, seq, isolate->factory()->NewRawOneByteString(character_count_), |
| 21 String); |
| 22 |
| 23 DisallowHeapAllocation no_gc; |
| 24 uint8_t* char_buffer = seq->GetChars(); |
| 25 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(), |
| 26 array_builder_.length()); |
| 27 joined_string = Handle<String>::cast(seq); |
| 28 } else { |
| 29 // Two-byte. |
| 30 Handle<SeqTwoByteString> seq; |
| 31 ASSIGN_RETURN_ON_EXCEPTION( |
| 32 isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_), |
| 33 String); |
| 34 |
| 35 DisallowHeapAllocation no_gc; |
| 36 uc16* char_buffer = seq->GetChars(); |
| 37 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(), |
| 38 array_builder_.length()); |
| 39 joined_string = Handle<String>::cast(seq); |
| 40 } |
| 41 return joined_string; |
| 42 } |
| 43 |
| 44 |
| 45 IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate) |
| 46 : isolate_(isolate), |
| 47 encoding_(String::ONE_BYTE_ENCODING), |
| 48 overflowed_(false), |
| 49 part_length_(kInitialPartLength), |
| 50 current_index_(0) { |
| 51 // Create an accumulator handle starting with the empty string. |
| 52 accumulator_ = Handle<String>(isolate->heap()->empty_string(), isolate); |
| 53 current_part_ = |
| 54 factory()->NewRawOneByteString(part_length_).ToHandleChecked(); |
| 55 } |
| 56 |
| 57 |
| 58 void IncrementalStringBuilder::Accumulate() { |
| 59 // Only accumulate fully written strings. Shrink first if necessary. |
| 60 DCHECK_EQ(current_index_, current_part()->length()); |
| 61 Handle<String> new_accumulator; |
| 62 if (accumulator()->length() + current_part()->length() > String::kMaxLength) { |
| 63 // Set the flag and carry on. Delay throwing the exception till the end. |
| 64 new_accumulator = factory()->empty_string(); |
| 65 overflowed_ = true; |
| 66 } else { |
| 67 new_accumulator = factory() |
| 68 ->NewConsString(accumulator(), current_part()) |
| 69 .ToHandleChecked(); |
| 70 } |
| 71 set_accumulator(new_accumulator); |
| 72 } |
| 73 |
| 74 |
| 75 void IncrementalStringBuilder::Extend() { |
| 76 Accumulate(); |
| 77 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
| 78 part_length_ *= kPartLengthGrowthFactor; |
| 79 } |
| 80 Handle<String> new_part; |
| 81 if (encoding_ == String::ONE_BYTE_ENCODING) { |
| 82 new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked(); |
| 83 } else { |
| 84 new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked(); |
| 85 } |
| 86 // Reuse the same handle to avoid being invalidated when exiting handle scope. |
| 87 set_current_part(new_part); |
| 88 current_index_ = 0; |
| 89 } |
| 90 |
| 91 |
| 92 MaybeHandle<String> IncrementalStringBuilder::Finish() { |
| 93 ShrinkCurrentPart(); |
| 94 Accumulate(); |
| 95 if (overflowed_) { |
| 96 THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String); |
| 97 } |
| 98 return accumulator(); |
| 99 } |
| 100 |
| 101 |
| 102 void IncrementalStringBuilder::AppendString(Handle<String> string) { |
| 103 ShrinkCurrentPart(); |
| 104 part_length_ = kInitialPartLength; // Allocate conservatively. |
| 105 Extend(); // Attach current part and allocate new part. |
| 106 Handle<String> concat = |
| 107 factory()->NewConsString(accumulator(), string).ToHandleChecked(); |
| 108 set_accumulator(concat); |
| 109 } |
| 110 } |
| 111 } // namespace v8::internal |
OLD | NEW |