1 // Copyright 2019 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_PARSING_LITERAL_BUFFER_H_ 6 #define V8_PARSING_LITERAL_BUFFER_H_ 7 8 #include "src/base/strings.h" 9 #include "src/base/vector.h" 10 #include "src/strings/unicode-decoder.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // LiteralBuffer - Collector of chars of literals. 16 class LiteralBuffer final { 17 public: LiteralBuffer()18 LiteralBuffer() : backing_store_(), position_(0), is_one_byte_(true) {} 19 ~LiteralBuffer()20 ~LiteralBuffer() { backing_store_.Dispose(); } 21 22 LiteralBuffer(const LiteralBuffer&) = delete; 23 LiteralBuffer& operator=(const LiteralBuffer&) = delete; 24 AddChar(char code_unit)25 V8_INLINE void AddChar(char code_unit) { 26 DCHECK(IsValidAscii(code_unit)); 27 AddOneByteChar(static_cast<byte>(code_unit)); 28 } 29 AddChar(base::uc32 code_unit)30 V8_INLINE void AddChar(base::uc32 code_unit) { 31 if (is_one_byte()) { 32 if (code_unit <= static_cast<base::uc32>(unibrow::Latin1::kMaxChar)) { 33 AddOneByteChar(static_cast<byte>(code_unit)); 34 return; 35 } 36 ConvertToTwoByte(); 37 } 38 AddTwoByteChar(code_unit); 39 } 40 is_one_byte()41 bool is_one_byte() const { return is_one_byte_; } 42 Equals(base::Vector<const char> keyword)43 bool Equals(base::Vector<const char> keyword) const { 44 return is_one_byte() && keyword.length() == position_ && 45 (memcmp(keyword.begin(), backing_store_.begin(), position_) == 0); 46 } 47 two_byte_literal()48 base::Vector<const uint16_t> two_byte_literal() const { 49 return literal<uint16_t>(); 50 } 51 one_byte_literal()52 base::Vector<const uint8_t> one_byte_literal() const { 53 return literal<uint8_t>(); 54 } 55 56 template <typename Char> literal()57 base::Vector<const Char> literal() const { 58 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); 59 DCHECK_EQ(position_ & (sizeof(Char) - 1), 0); 60 return base::Vector<const Char>( 61 reinterpret_cast<const Char*>(backing_store_.begin()), 62 position_ >> (sizeof(Char) - 1)); 63 } 64 length()65 int length() const { return is_one_byte() ? position_ : (position_ >> 1); } 66 Start()67 void Start() { 68 position_ = 0; 69 is_one_byte_ = true; 70 } 71 72 template <typename IsolateT> 73 Handle<String> Internalize(IsolateT* isolate) const; 74 75 private: 76 static const int kInitialCapacity = 16; 77 static const int kGrowthFactor = 4; 78 static const int kMaxGrowth = 1 * MB; 79 IsValidAscii(char code_unit)80 inline bool IsValidAscii(char code_unit) { 81 // Control characters and printable characters span the range of 82 // valid ASCII characters (0-127). Chars are unsigned on some 83 // platforms which causes compiler warnings if the validity check 84 // tests the lower bound >= 0 as it's always true. 85 return iscntrl(code_unit) || isprint(code_unit); 86 } 87 AddOneByteChar(byte one_byte_char)88 V8_INLINE void AddOneByteChar(byte one_byte_char) { 89 DCHECK(is_one_byte()); 90 if (position_ >= backing_store_.length()) ExpandBuffer(); 91 backing_store_[position_] = one_byte_char; 92 position_ += kOneByteSize; 93 } 94 95 void AddTwoByteChar(base::uc32 code_unit); 96 int NewCapacity(int min_capacity); 97 void ExpandBuffer(); 98 void ConvertToTwoByte(); 99 100 base::Vector<byte> backing_store_; 101 int position_; 102 103 bool is_one_byte_; 104 }; 105 106 } // namespace internal 107 } // namespace v8 108 109 #endif // V8_PARSING_LITERAL_BUFFER_H_ 110