| // 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; |
| } |
| |
| template <typename LocalIsolate> |
| Handle<String> Internalize(LocalIsolate* 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_ |