5 #ifndef V8_STRING_BUILDER_INL_H_ 6 #define V8_STRING_BUILDER_INL_H_ 8 #include "src/assert-scope.h" 9 #include "src/handles-inl.h" 10 #include "src/heap/factory.h" 11 #include "src/isolate.h" 12 #include "src/objects.h" 13 #include "src/objects/fixed-array.h" 14 #include "src/objects/string-inl.h" 15 #include "src/utils.h" 20 const int kStringBuilderConcatHelperLengthBits = 11;
21 const int kStringBuilderConcatHelperPositionBits = 19;
23 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
24 StringBuilderSubstringLength;
25 typedef BitField<
int, kStringBuilderConcatHelperLengthBits,
26 kStringBuilderConcatHelperPositionBits>
27 StringBuilderSubstringPosition;
29 template <
typename sink
char>
30 void StringBuilderConcatHelper(String special, sinkchar* sink,
31 FixedArray fixed_array,
int array_length);
35 int StringBuilderConcatLength(
int special_length, FixedArray fixed_array,
36 int array_length,
bool* one_byte);
43 bool HasCapacity(
int elements);
44 void EnsureCapacity(
Isolate* isolate,
int elements);
51 int length() {
return length_; }
60 bool has_non_smi_elements_;
66 int estimated_part_count);
71 int length = to - from;
73 if (StringBuilderSubstringLength::is_valid(length) &&
74 StringBuilderSubstringPosition::is_valid(from)) {
75 int encoded_slice = StringBuilderSubstringLength::encode(length) |
76 StringBuilderSubstringPosition::encode(from);
77 builder->Add(Smi::FromInt(encoded_slice));
80 builder->Add(Smi::FromInt(-length));
81 builder->Add(Smi::FromInt(from));
85 void EnsureCapacity(
int elements);
87 void AddSubjectSlice(
int from,
int to) {
88 AddSubjectSlice(&array_builder_, from, to);
89 IncrementCharacterCount(to - from);
96 void IncrementCharacterCount(
int by) {
97 if (character_count_ > String::kMaxLength - by) {
98 STATIC_ASSERT(String::kMaxLength < kMaxInt);
99 character_count_ = kMaxInt;
101 character_count_ += by;
106 void AddElement(
Object* element);
111 int character_count_;
119 V8_INLINE String::Encoding CurrentEncoding() {
return encoding_; }
121 template <
typename SrcChar,
typename DestChar>
122 V8_INLINE
void Append(SrcChar c);
124 V8_INLINE
void AppendCharacter(uint8_t c) {
125 if (encoding_ == String::ONE_BYTE_ENCODING) {
126 Append<uint8_t, uint8_t>(c);
128 Append<uint8_t, uc16>(c);
132 V8_INLINE
void AppendCString(
const char* s) {
133 const uint8_t* u =
reinterpret_cast<const uint8_t*
>(s);
134 if (encoding_ == String::ONE_BYTE_ENCODING) {
135 while (*u !=
'\0') Append<uint8_t, uint8_t>(*(u++));
137 while (*u !=
'\0') Append<uint8_t, uc16>(*(u++));
141 V8_INLINE
void AppendCString(
const uc16* s) {
142 if (encoding_ == String::ONE_BYTE_ENCODING) {
143 while (*s !=
'\0') Append<uc16, uint8_t>(*(s++));
145 while (*s !=
'\0') Append<uc16, uc16>(*(s++));
149 V8_INLINE
bool CurrentPartCanFit(
int length) {
150 return part_length_ - current_index_ > length;
157 V8_INLINE
int EscapedLengthIfCurrentPartFits(
int length) {
158 if (length > kMaxPartLength)
return 0;
159 STATIC_ASSERT((kMaxPartLength << 3) <= String::kMaxLength);
162 int worst_case_length = length << 3;
163 return CurrentPartCanFit(worst_case_length) ? worst_case_length : 0;
170 V8_INLINE
bool HasOverflowed()
const {
return overflowed_; }
175 void ChangeEncoding() {
176 DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
178 encoding_ = String::TWO_BYTE_ENCODING;
182 template <
typename DestChar>
186 DCHECK(string->IsSeqOneByteString() ||
string->IsSeqTwoByteString());
187 if (
sizeof(DestChar) == 1) {
188 start_ =
reinterpret_cast<DestChar*
>(
191 start_ =
reinterpret_cast<DestChar*
>(
197 V8_INLINE
void Append(DestChar c) { *(cursor_++) = c; }
198 V8_INLINE
void AppendCString(
const char* s) {
199 const uint8_t* u =
reinterpret_cast<const uint8_t*
>(s);
200 while (*u !=
'\0') Append(*(u++));
203 int written() {
return static_cast<int>(cursor_ - start_); }
208 DISALLOW_HEAP_ALLOCATION(no_gc_);
211 template <
typename DestChar>
216 DCHECK(string->length() >= required_length);
231 template <
typename DestChar>
237 DCHECK(builder->CurrentPartCanFit(required_length));
249 Factory* factory() {
return isolate_->factory(); }
254 *accumulator_.location() =
string->ptr();
257 V8_INLINE Handle<String> current_part() {
return current_part_; }
259 V8_INLINE
void set_current_part(Handle<String>
string) {
260 *current_part_.location() =
string->ptr();
264 void Accumulate(Handle<String> new_part);
270 void ShrinkCurrentPart() {
271 DCHECK(current_index_ < part_length_);
272 set_current_part(SeqString::Truncate(
273 Handle<SeqString>::cast(current_part()), current_index_));
276 static const int kInitialPartLength = 32;
277 static const int kMaxPartLength = 16 * 1024;
278 static const int kPartLengthGrowthFactor = 2;
281 String::Encoding encoding_;
285 Handle<String> accumulator_;
286 Handle<String> current_part_;
289 template <
typename SrcChar,
typename DestChar>
290 void IncrementalStringBuilder::Append(SrcChar c) {
291 DCHECK_EQ(encoding_ == String::ONE_BYTE_ENCODING,
sizeof(DestChar) == 1);
292 if (
sizeof(DestChar) == 1) {
293 DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
294 SeqOneByteString::cast(*current_part_)
295 ->SeqOneByteStringSet(current_index_++, c);
297 DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding_);
298 SeqTwoByteString::cast(*current_part_)
299 ->SeqTwoByteStringSet(current_index_++, c);
301 if (current_index_ == part_length_) Extend();
306 #endif // V8_STRING_BUILDER_INL_H_