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