| Index: src/string-builder.h
|
| diff --git a/src/runtime/string-builder.h b/src/string-builder.h
|
| similarity index 62%
|
| rename from src/runtime/string-builder.h
|
| rename to src/string-builder.h
|
| index 890b7f6be1bb0198c3681890991c29e142d42bf4..f64f679870daa00def5f22bb2306764b72a9bafd 100644
|
| --- a/src/runtime/string-builder.h
|
| +++ b/src/string-builder.h
|
| @@ -2,8 +2,10 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#ifndef V8_RUNTIME_STRING_BUILDER_H_
|
| -#define V8_RUNTIME_STRING_BUILDER_H_
|
| +#ifndef V8_STRING_BUILDER_H_
|
| +#define V8_STRING_BUILDER_H_
|
| +
|
| +#include "src/v8.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -233,39 +235,7 @@ class ReplacementStringBuilder {
|
| }
|
|
|
|
|
| - MaybeHandle<String> 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;
|
| - }
|
| + MaybeHandle<String> ToString();
|
|
|
|
|
| void IncrementCharacterCount(int by) {
|
| @@ -290,7 +260,171 @@ class ReplacementStringBuilder {
|
| int character_count_;
|
| bool is_one_byte_;
|
| };
|
| +
|
| +
|
| +class IncrementalStringBuilder {
|
| + public:
|
| + explicit IncrementalStringBuilder(Isolate* isolate);
|
| +
|
| + INLINE(String::Encoding CurrentEncoding()) { return encoding_; }
|
| +
|
| + template <typename SrcChar, typename DestChar>
|
| + INLINE(void Append(SrcChar c));
|
| +
|
| + INLINE(void AppendCharacter(uint8_t c)) {
|
| + if (encoding_ == String::ONE_BYTE_ENCODING) {
|
| + Append<uint8_t, uint8_t>(c);
|
| + } else {
|
| + Append<uint8_t, uc16>(c);
|
| + }
|
| + }
|
| +
|
| + INLINE(void AppendCString(const char* s)) {
|
| + const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
|
| + if (encoding_ == String::ONE_BYTE_ENCODING) {
|
| + while (*u != '\0') Append<uint8_t, uint8_t>(*(u++));
|
| + } else {
|
| + while (*u != '\0') Append<uint8_t, uc16>(*(u++));
|
| + }
|
| + }
|
| +
|
| + INLINE(bool CurrentPartCanFit(int length)) {
|
| + return part_length_ - current_index_ > length;
|
| + }
|
| +
|
| + void AppendString(Handle<String> string);
|
| +
|
| + MaybeHandle<String> Finish();
|
| +
|
| + // Change encoding to two-byte.
|
| + void ChangeEncoding() {
|
| + DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
|
| + ShrinkCurrentPart();
|
| + encoding_ = String::TWO_BYTE_ENCODING;
|
| + Extend();
|
| + }
|
| +
|
| + template <typename DestChar>
|
| + class NoExtend {
|
| + public:
|
| + explicit NoExtend(Handle<String> string, int offset) {
|
| + DCHECK(string->IsSeqOneByteString() || string->IsSeqTwoByteString());
|
| + if (sizeof(DestChar) == 1) {
|
| + start_ = reinterpret_cast<DestChar*>(
|
| + Handle<SeqOneByteString>::cast(string)->GetChars() + offset);
|
| + } else {
|
| + start_ = reinterpret_cast<DestChar*>(
|
| + Handle<SeqTwoByteString>::cast(string)->GetChars() + offset);
|
| + }
|
| + cursor_ = start_;
|
| + }
|
| +
|
| + INLINE(void Append(DestChar c)) { *(cursor_++) = c; }
|
| + INLINE(void AppendCString(const char* s)) {
|
| + const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
|
| + while (*u != '\0') Append(*(u++));
|
| + }
|
| +
|
| + int written() { return cursor_ - start_; }
|
| +
|
| + private:
|
| + DestChar* start_;
|
| + DestChar* cursor_;
|
| + DisallowHeapAllocation no_gc_;
|
| + };
|
| +
|
| + template <typename DestChar>
|
| + class NoExtendString : public NoExtend<DestChar> {
|
| + public:
|
| + NoExtendString(Handle<String> string, int required_length)
|
| + : NoExtend<DestChar>(string, 0), string_(string) {
|
| + DCHECK(string->length() >= required_length);
|
| + }
|
| +
|
| + ~NoExtendString() {
|
| + Handle<SeqString> string = Handle<SeqString>::cast(string_);
|
| + int length = NoExtend<DestChar>::written();
|
| + *string_.location() = *SeqString::Truncate(string, length);
|
| + }
|
| +
|
| + private:
|
| + Handle<String> string_;
|
| + };
|
| +
|
| + template <typename DestChar>
|
| + class NoExtendBuilder : public NoExtend<DestChar> {
|
| + public:
|
| + NoExtendBuilder(IncrementalStringBuilder* builder, int required_length)
|
| + : NoExtend<DestChar>(builder->current_part(), builder->current_index_),
|
| + builder_(builder) {
|
| + DCHECK(builder->CurrentPartCanFit(required_length));
|
| + }
|
| +
|
| + ~NoExtendBuilder() {
|
| + builder_->current_index_ += NoExtend<DestChar>::written();
|
| + }
|
| +
|
| + private:
|
| + IncrementalStringBuilder* builder_;
|
| + };
|
| +
|
| + private:
|
| + Factory* factory() { return isolate_->factory(); }
|
| +
|
| + INLINE(Handle<String> accumulator()) { return accumulator_; }
|
| +
|
| + INLINE(void set_accumulator(Handle<String> string)) {
|
| + *accumulator_.location() = *string;
|
| + }
|
| +
|
| + INLINE(Handle<String> current_part()) { return current_part_; }
|
| +
|
| + INLINE(void set_current_part(Handle<String> string)) {
|
| + *current_part_.location() = *string;
|
| + }
|
| +
|
| + // Add the current part to the accumulator.
|
| + void Accumulate();
|
| +
|
| + // Finish the current part and allocate a new part.
|
| + void Extend();
|
| +
|
| + // Shrink current part to the right size.
|
| + void ShrinkCurrentPart() {
|
| + DCHECK(current_index_ < part_length_);
|
| + set_current_part(SeqString::Truncate(
|
| + Handle<SeqString>::cast(current_part()), current_index_));
|
| + }
|
| +
|
| + static const int kInitialPartLength = 32;
|
| + static const int kMaxPartLength = 16 * 1024;
|
| + static const int kPartLengthGrowthFactor = 2;
|
| +
|
| + Isolate* isolate_;
|
| + String::Encoding encoding_;
|
| + bool overflowed_;
|
| + int part_length_;
|
| + int current_index_;
|
| + Handle<String> accumulator_;
|
| + Handle<String> current_part_;
|
| +};
|
| +
|
| +
|
| +template <typename SrcChar, typename DestChar>
|
| +void IncrementalStringBuilder::Append(SrcChar c) {
|
| + DCHECK_EQ(encoding_ == String::ONE_BYTE_ENCODING, sizeof(DestChar) == 1);
|
| + if (sizeof(DestChar) == 1) {
|
| + DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
|
| + SeqOneByteString::cast(*current_part_)
|
| + ->SeqOneByteStringSet(current_index_++, c);
|
| + } else {
|
| + DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding_);
|
| + SeqTwoByteString::cast(*current_part_)
|
| + ->SeqTwoByteStringSet(current_index_++, c);
|
| + }
|
| + if (current_index_ == part_length_) Extend();
|
| +}
|
| }
|
| } // namespace v8::internal
|
|
|
| -#endif // V8_RUNTIME_STRING_BUILDER_H_
|
| +#endif // V8_STRING_BUILDER_H_
|
|
|