literal-buffer.h 3.07 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include "src/base/strings.h"
9
#include "src/base/vector.h"
10
#include "src/strings/unicode-decoder.h"
11 12 13 14 15 16 17 18 19 20 21

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(); }

22 23 24
  LiteralBuffer(const LiteralBuffer&) = delete;
  LiteralBuffer& operator=(const LiteralBuffer&) = delete;

25 26 27 28 29
  V8_INLINE void AddChar(char code_unit) {
    DCHECK(IsValidAscii(code_unit));
    AddOneByteChar(static_cast<byte>(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 34 35 36 37 38 39 40 41 42
        AddOneByteChar(static_cast<byte>(code_unit));
        return;
      }
      ConvertToTwoByte();
    }
    AddTwoByteChar(code_unit);
  }

  bool is_one_byte() const { return is_one_byte_; }

43
  bool Equals(base::Vector<const char> keyword) const {
44 45 46 47
    return is_one_byte() && keyword.length() == position_ &&
           (memcmp(keyword.begin(), backing_store_.begin(), position_) == 0);
  }

48
  base::Vector<const uint16_t> two_byte_literal() const {
49 50 51
    return literal<uint16_t>();
  }

52 53 54
  base::Vector<const uint8_t> one_byte_literal() const {
    return literal<uint8_t>();
  }
55 56

  template <typename Char>
57
  base::Vector<const Char> literal() const {
58 59
    DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
    DCHECK_EQ(position_ & (sizeof(Char) - 1), 0);
60
    return base::Vector<const Char>(
61 62 63 64 65 66 67 68 69 70 71
        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;
  }

72 73
  template <typename IsolateT>
  Handle<String> Internalize(IsolateT* isolate) const;
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

 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;
  }

95
  void AddTwoByteChar(base::uc32 code_unit);
96 97 98 99
  int NewCapacity(int min_capacity);
  void ExpandBuffer();
  void ConvertToTwoByte();

100
  base::Vector<byte> backing_store_;
101 102 103 104 105 106 107 108 109
  int position_;

  bool is_one_byte_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_LITERAL_BUFFER_H_