blob: b1f695ad9b5918381752977b3041e70490aa92af [file]
// Copyright 2024 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.
#ifndef V8_STRINGS_STRING_BUILDER_H_
#define V8_STRINGS_STRING_BUILDER_H_
#include "src/common/assert-scope.h"
#include "src/handles/handles.h"
#include "src/objects/heap-object.h"
#include "src/objects/string.h"
namespace v8 {
namespace internal {
class FixedArrayBuilder {
public:
explicit FixedArrayBuilder(Isolate* isolate, uint32_t initial_capacity);
explicit FixedArrayBuilder(DirectHandle<FixedArray> backing_store);
// Creates a FixedArrayBuilder which allocates its backing store lazily when
// EnsureCapacity is called.
static FixedArrayBuilder Lazy(Isolate* isolate);
bool HasCapacity(uint32_t elements);
void EnsureCapacity(Isolate* isolate, uint32_t elements);
void Add(Tagged<Object> value);
void Add(Tagged<Smi> value);
DirectHandle<FixedArray> array() { return array_; }
// The functions return an alias instead of uint32_t to force appropriate
// conversions at the callsites.
SafeHeapObjectSize length() { return SafeHeapObjectSize(length_); }
SafeHeapObjectSize capacity();
private:
explicit FixedArrayBuilder(Isolate* isolate);
DirectHandle<FixedArray> array_;
uint32_t length_;
bool has_non_smi_elements_;
};
class ReplacementStringBuilder {
public:
ReplacementStringBuilder(Heap* heap, DirectHandle<String> subject,
uint32_t estimated_part_count);
// Caution: Callers must ensure the builder has enough capacity.
static inline void AddSubjectSlice(FixedArrayBuilder* builder, int from,
int to);
inline void AddSubjectSlice(int from, int to);
void AddString(DirectHandle<String> string);
MaybeDirectHandle<String> ToString();
void IncrementCharacterCount(uint32_t by) {
if (character_count_ > String::kMaxLength - by) {
static_assert(String::kMaxLength < kMaxInt);
character_count_ = kMaxInt;
} else {
character_count_ += by;
}
}
private:
void AddElement(DirectHandle<Object> element);
void EnsureCapacity(uint32_t elements);
Heap* heap_;
FixedArrayBuilder array_builder_;
DirectHandle<String> subject_;
uint32_t character_count_;
bool is_one_byte_;
};
class IncrementalStringBuilder {
public:
explicit IncrementalStringBuilder(Isolate* isolate);
V8_INLINE String::Encoding CurrentEncoding() { return encoding_; }
template <typename SrcChar, typename DestChar>
V8_INLINE void Append(SrcChar c);
V8_INLINE void AppendCharacter(uint8_t c);
template <int N>
V8_INLINE void AppendCStringLiteral(const char (&literal)[N]);
template <typename SrcChar>
V8_INLINE void AppendCString(const SrcChar* s);
V8_INLINE void AppendString(std::string_view str);
V8_INLINE void AppendInt(int i);
V8_INLINE bool CurrentPartCanFit(int length) {
return part_length_ - current_index_ > length;
}
// We make a rough estimate to find out if the current string can be
// serialized without allocating a new string part.
V8_INLINE int EscapedLengthIfCurrentPartFits(int length);
void AppendString(DirectHandle<String> string);
// Appends {string} if its length is less than {max_length}, otherwise
// appends that prefix plus "<...>". Useful for error messages.
void AppendStringCapped(DirectHandle<String> string, uint32_t max_length);
MaybeDirectHandle<String> Finish();
V8_INLINE bool HasOverflowed() const { return overflowed_; }
int Length() const;
// Change encoding to two-byte.
V8_INLINE void ChangeEncoding();
Isolate* isolate() { return isolate_; }
private:
V8_INLINE Factory* factory();
V8_INLINE DirectHandle<String> accumulator() { return accumulator_; }
V8_INLINE void set_accumulator(DirectHandle<String> string) {
accumulator_.SetValue(*string);
}
V8_INLINE DirectHandle<String> current_part() { return current_part_; }
V8_INLINE void set_current_part(DirectHandle<String> string) {
current_part_.SetValue(*string);
}
// Add the current part to the accumulator.
void Accumulate(DirectHandle<String> new_part);
// Finish the current part and allocate a new part.
void Extend();
bool HasValidCurrentIndex() const;
// Shrink current part to the right size.
V8_INLINE void ShrinkCurrentPart();
void AppendStringByCopy(DirectHandle<String> string);
bool CanAppendByCopy(DirectHandle<String> string);
static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024;
static const int kPartLengthGrowthFactor = 2;
// sizeof(string) includes \0.
static const int kIntToStringViewBufferSize = sizeof("-2147483648") - 1;
Isolate* isolate_;
String::Encoding encoding_;
bool overflowed_;
int part_length_;
int current_index_;
DirectHandle<String> accumulator_;
DirectHandle<String> current_part_;
};
} // namespace internal
} // namespace v8
#endif // V8_STRINGS_STRING_BUILDER_H_