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
12namespace v8 {
13namespace internal {
14
15// LiteralBuffer -  Collector of chars of literals.
16class LiteralBuffer final {
17 public:
18  LiteralBuffer() : backing_store_(), position_(0), is_one_byte_(true) {}
19
20  ~LiteralBuffer() { backing_store_.Dispose(); }
21
22  LiteralBuffer(const LiteralBuffer&) = delete;
23  LiteralBuffer& operator=(const LiteralBuffer&) = delete;
24
25  V8_INLINE void AddChar(char code_unit) {
26    DCHECK(IsValidAscii(code_unit));
27    AddOneByteChar(static_cast<byte>(code_unit));
28  }
29
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
41  bool is_one_byte() const { return is_one_byte_; }
42
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
48  base::Vector<const uint16_t> two_byte_literal() const {
49    return literal<uint16_t>();
50  }
51
52  base::Vector<const uint8_t> one_byte_literal() const {
53    return literal<uint8_t>();
54  }
55
56  template <typename Char>
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
65  int length() const { return is_one_byte() ? position_ : (position_ >> 1); }
66
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
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
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