// Copyright 2019 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_PARSING_LITERAL_BUFFER_H_ #define V8_PARSING_LITERAL_BUFFER_H_ #include "src/strings/unicode-decoder.h" #include "src/utils/vector.h" namespace v8 { namespace internal { // LiteralBuffer - Collector of chars of literals. class LiteralBuffer final { public: LiteralBuffer() : backing_store_(), position_(0), is_one_byte_(true) {} ~LiteralBuffer() { backing_store_.Dispose(); } V8_INLINE void AddChar(char code_unit) { DCHECK(IsValidAscii(code_unit)); AddOneByteChar(static_cast<byte>(code_unit)); } V8_INLINE void AddChar(uc32 code_unit) { if (is_one_byte()) { if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) { AddOneByteChar(static_cast<byte>(code_unit)); return; } ConvertToTwoByte(); } AddTwoByteChar(code_unit); } bool is_one_byte() const { return is_one_byte_; } bool Equals(Vector<const char> keyword) const { return is_one_byte() && keyword.length() == position_ && (memcmp(keyword.begin(), backing_store_.begin(), position_) == 0); } Vector<const uint16_t> two_byte_literal() const { return literal<uint16_t>(); } Vector<const uint8_t> one_byte_literal() const { return literal<uint8_t>(); } template <typename Char> Vector<const Char> literal() const { DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); DCHECK_EQ(position_ & (sizeof(Char) - 1), 0); return Vector<const Char>( reinterpret_cast<const Char*>(backing_store_.begin()), position_ >> (sizeof(Char) - 1)); } int length() const { return is_one_byte() ? position_ : (position_ >> 1); } void Start() { position_ = 0; is_one_byte_ = true; } Handle<String> Internalize(Isolate* isolate) const; private: static const int kInitialCapacity = 16; static const int kGrowthFactor = 4; static const int kMaxGrowth = 1 * MB; inline bool IsValidAscii(char code_unit) { // Control characters and printable characters span the range of // valid ASCII characters (0-127). Chars are unsigned on some // platforms which causes compiler warnings if the validity check // tests the lower bound >= 0 as it's always true. return iscntrl(code_unit) || isprint(code_unit); } V8_INLINE void AddOneByteChar(byte one_byte_char) { DCHECK(is_one_byte()); if (position_ >= backing_store_.length()) ExpandBuffer(); backing_store_[position_] = one_byte_char; position_ += kOneByteSize; } void AddTwoByteChar(uc32 code_unit); int NewCapacity(int min_capacity); void ExpandBuffer(); void ConvertToTwoByte(); Vector<byte> backing_store_; int position_; bool is_one_byte_; DISALLOW_COPY_AND_ASSIGN(LiteralBuffer); }; } // namespace internal } // namespace v8 #endif // V8_PARSING_LITERAL_BUFFER_H_