11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_STRINGS_STRING_STREAM_H_
61cb0ef41Sopenharmony_ci#define V8_STRINGS_STRING_STREAM_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <memory>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/small-vector.h"
111cb0ef41Sopenharmony_ci#include "src/base/strings.h"
121cb0ef41Sopenharmony_ci#include "src/base/vector.h"
131cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
141cb0ef41Sopenharmony_ci#include "src/objects/heap-object.h"
151cb0ef41Sopenharmony_ci#include "src/utils/allocation.h"
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace v8 {
181cb0ef41Sopenharmony_cinamespace internal {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Forward declarations.
211cb0ef41Sopenharmony_ciclass ByteArray;
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciclass StringAllocator {
241cb0ef41Sopenharmony_ci public:
251cb0ef41Sopenharmony_ci  virtual ~StringAllocator() = default;
261cb0ef41Sopenharmony_ci  // Allocate a number of bytes.
271cb0ef41Sopenharmony_ci  virtual char* allocate(unsigned bytes) = 0;
281cb0ef41Sopenharmony_ci  // Allocate a larger number of bytes and copy the old buffer to the new one.
291cb0ef41Sopenharmony_ci  // bytes is an input and output parameter passing the old size of the buffer
301cb0ef41Sopenharmony_ci  // and returning the new size.  If allocation fails then we return the old
311cb0ef41Sopenharmony_ci  // buffer and do not increase the size.
321cb0ef41Sopenharmony_ci  virtual char* grow(unsigned* bytes) = 0;
331cb0ef41Sopenharmony_ci};
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci// Normal allocator uses new[] and delete[].
361cb0ef41Sopenharmony_ciclass HeapStringAllocator final : public StringAllocator {
371cb0ef41Sopenharmony_ci public:
381cb0ef41Sopenharmony_ci  ~HeapStringAllocator() override { DeleteArray(space_); }
391cb0ef41Sopenharmony_ci  char* allocate(unsigned bytes) override;
401cb0ef41Sopenharmony_ci  char* grow(unsigned* bytes) override;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci private:
431cb0ef41Sopenharmony_ci  char* space_;
441cb0ef41Sopenharmony_ci};
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciclass FixedStringAllocator final : public StringAllocator {
471cb0ef41Sopenharmony_ci public:
481cb0ef41Sopenharmony_ci  FixedStringAllocator(char* buffer, unsigned length)
491cb0ef41Sopenharmony_ci      : buffer_(buffer), length_(length) {}
501cb0ef41Sopenharmony_ci  ~FixedStringAllocator() override = default;
511cb0ef41Sopenharmony_ci  FixedStringAllocator(const FixedStringAllocator&) = delete;
521cb0ef41Sopenharmony_ci  FixedStringAllocator& operator=(const FixedStringAllocator&) = delete;
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  char* allocate(unsigned bytes) override;
551cb0ef41Sopenharmony_ci  char* grow(unsigned* bytes) override;
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci private:
581cb0ef41Sopenharmony_ci  char* buffer_;
591cb0ef41Sopenharmony_ci  unsigned length_;
601cb0ef41Sopenharmony_ci};
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_citemplate <std::size_t kInlineSize>
631cb0ef41Sopenharmony_ciclass SmallStringOptimizedAllocator final : public StringAllocator {
641cb0ef41Sopenharmony_ci public:
651cb0ef41Sopenharmony_ci  using SmallVector = base::SmallVector<char, kInlineSize>;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  explicit SmallStringOptimizedAllocator(SmallVector* vector) V8_NOEXCEPT
681cb0ef41Sopenharmony_ci      : vector_(vector) {}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  char* allocate(unsigned bytes) override {
711cb0ef41Sopenharmony_ci    vector_->resize_no_init(bytes);
721cb0ef41Sopenharmony_ci    return vector_->data();
731cb0ef41Sopenharmony_ci  }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  char* grow(unsigned* bytes) override {
761cb0ef41Sopenharmony_ci    unsigned new_bytes = *bytes * 2;
771cb0ef41Sopenharmony_ci    // Check for overflow.
781cb0ef41Sopenharmony_ci    if (new_bytes <= *bytes) {
791cb0ef41Sopenharmony_ci      return vector_->data();
801cb0ef41Sopenharmony_ci    }
811cb0ef41Sopenharmony_ci    vector_->resize_no_init(new_bytes);
821cb0ef41Sopenharmony_ci    *bytes = new_bytes;
831cb0ef41Sopenharmony_ci    return vector_->data();
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci private:
871cb0ef41Sopenharmony_ci  SmallVector* vector_;
881cb0ef41Sopenharmony_ci};
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ciclass StringStream final {
911cb0ef41Sopenharmony_ci  class FmtElm final {
921cb0ef41Sopenharmony_ci   public:
931cb0ef41Sopenharmony_ci    FmtElm(int value) : FmtElm(INT) {  // NOLINT
941cb0ef41Sopenharmony_ci      data_.u_int_ = value;
951cb0ef41Sopenharmony_ci    }
961cb0ef41Sopenharmony_ci    explicit FmtElm(double value) : FmtElm(DOUBLE) {  // NOLINT
971cb0ef41Sopenharmony_ci      data_.u_double_ = value;
981cb0ef41Sopenharmony_ci    }
991cb0ef41Sopenharmony_ci    FmtElm(const char* value) : FmtElm(C_STR) {  // NOLINT
1001cb0ef41Sopenharmony_ci      data_.u_c_str_ = value;
1011cb0ef41Sopenharmony_ci    }
1021cb0ef41Sopenharmony_ci    FmtElm(const base::Vector<const base::uc16>& value)  // NOLINT
1031cb0ef41Sopenharmony_ci        : FmtElm(LC_STR) {
1041cb0ef41Sopenharmony_ci      data_.u_lc_str_ = &value;
1051cb0ef41Sopenharmony_ci    }
1061cb0ef41Sopenharmony_ci    FmtElm(Object value) : FmtElm(OBJ) {  // NOLINT
1071cb0ef41Sopenharmony_ci      data_.u_obj_ = value.ptr();
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci    FmtElm(Handle<Object> value) : FmtElm(HANDLE) {  // NOLINT
1101cb0ef41Sopenharmony_ci      data_.u_handle_ = value.location();
1111cb0ef41Sopenharmony_ci    }
1121cb0ef41Sopenharmony_ci    FmtElm(void* value) : FmtElm(POINTER) {  // NOLINT
1131cb0ef41Sopenharmony_ci      data_.u_pointer_ = value;
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci   private:
1171cb0ef41Sopenharmony_ci    friend class StringStream;
1181cb0ef41Sopenharmony_ci    enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci#ifdef DEBUG
1211cb0ef41Sopenharmony_ci    Type type_;
1221cb0ef41Sopenharmony_ci    explicit FmtElm(Type type) : type_(type) {}
1231cb0ef41Sopenharmony_ci#else
1241cb0ef41Sopenharmony_ci    explicit FmtElm(Type) {}
1251cb0ef41Sopenharmony_ci#endif
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci    union {
1281cb0ef41Sopenharmony_ci      int u_int_;
1291cb0ef41Sopenharmony_ci      double u_double_;
1301cb0ef41Sopenharmony_ci      const char* u_c_str_;
1311cb0ef41Sopenharmony_ci      const base::Vector<const base::uc16>* u_lc_str_;
1321cb0ef41Sopenharmony_ci      Address u_obj_;
1331cb0ef41Sopenharmony_ci      Address* u_handle_;
1341cb0ef41Sopenharmony_ci      void* u_pointer_;
1351cb0ef41Sopenharmony_ci    } data_;
1361cb0ef41Sopenharmony_ci  };
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci public:
1391cb0ef41Sopenharmony_ci  enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
1401cb0ef41Sopenharmony_ci  explicit StringStream(StringAllocator* allocator,
1411cb0ef41Sopenharmony_ci                        ObjectPrintMode object_print_mode = kPrintObjectVerbose)
1421cb0ef41Sopenharmony_ci      : allocator_(allocator),
1431cb0ef41Sopenharmony_ci        object_print_mode_(object_print_mode),
1441cb0ef41Sopenharmony_ci        capacity_(kInitialCapacity),
1451cb0ef41Sopenharmony_ci        length_(0),
1461cb0ef41Sopenharmony_ci        buffer_(allocator_->allocate(kInitialCapacity)) {
1471cb0ef41Sopenharmony_ci    buffer_[0] = 0;
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  bool Put(char c);
1511cb0ef41Sopenharmony_ci  bool Put(String str);
1521cb0ef41Sopenharmony_ci  bool Put(String str, int start, int end);
1531cb0ef41Sopenharmony_ci  void Add(const char* format) { Add(base::CStrVector(format)); }
1541cb0ef41Sopenharmony_ci  void Add(base::Vector<const char> format) {
1551cb0ef41Sopenharmony_ci    Add(format, base::Vector<FmtElm>());
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  template <typename... Args>
1591cb0ef41Sopenharmony_ci  void Add(const char* format, Args... args) {
1601cb0ef41Sopenharmony_ci    Add(base::CStrVector(format), args...);
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  template <typename... Args>
1641cb0ef41Sopenharmony_ci  void Add(base::Vector<const char> format, Args... args) {
1651cb0ef41Sopenharmony_ci    FmtElm elems[]{args...};
1661cb0ef41Sopenharmony_ci    Add(format, base::ArrayVector(elems));
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  // Getting the message out.
1701cb0ef41Sopenharmony_ci  void OutputToFile(FILE* out);
1711cb0ef41Sopenharmony_ci  void OutputToStdOut() { OutputToFile(stdout); }
1721cb0ef41Sopenharmony_ci  void Log(Isolate* isolate);
1731cb0ef41Sopenharmony_ci  Handle<String> ToString(Isolate* isolate);
1741cb0ef41Sopenharmony_ci  std::unique_ptr<char[]> ToCString() const;
1751cb0ef41Sopenharmony_ci  int length() const { return length_; }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  // Object printing support.
1781cb0ef41Sopenharmony_ci  void PrintName(Object o);
1791cb0ef41Sopenharmony_ci  void PrintFixedArray(FixedArray array, unsigned int limit);
1801cb0ef41Sopenharmony_ci  void PrintByteArray(ByteArray ba);
1811cb0ef41Sopenharmony_ci  void PrintUsingMap(JSObject js_object);
1821cb0ef41Sopenharmony_ci  void PrintPrototype(JSFunction fun, Object receiver);
1831cb0ef41Sopenharmony_ci  void PrintSecurityTokenIfChanged(JSFunction function);
1841cb0ef41Sopenharmony_ci  // NOTE: Returns the code in the output parameter.
1851cb0ef41Sopenharmony_ci  void PrintFunction(JSFunction function, Object receiver, Code* code);
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  // Reset the stream.
1881cb0ef41Sopenharmony_ci  void Reset() {
1891cb0ef41Sopenharmony_ci    length_ = 0;
1901cb0ef41Sopenharmony_ci    buffer_[0] = 0;
1911cb0ef41Sopenharmony_ci  }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  // Mentioned object cache support.
1941cb0ef41Sopenharmony_ci  void PrintMentionedObjectCache(Isolate* isolate);
1951cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE static void ClearMentionedObjectCache(Isolate* isolate);
1961cb0ef41Sopenharmony_ci#ifdef DEBUG
1971cb0ef41Sopenharmony_ci  bool IsMentionedObjectCacheClear(Isolate* isolate);
1981cb0ef41Sopenharmony_ci#endif
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  static const int kInitialCapacity = 16;
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci private:
2031cb0ef41Sopenharmony_ci  void Add(base::Vector<const char> format, base::Vector<FmtElm> elms);
2041cb0ef41Sopenharmony_ci  void PrintObject(Object obj);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  StringAllocator* allocator_;
2071cb0ef41Sopenharmony_ci  ObjectPrintMode object_print_mode_;
2081cb0ef41Sopenharmony_ci  unsigned capacity_;
2091cb0ef41Sopenharmony_ci  unsigned length_;  // does not include terminating 0-character
2101cb0ef41Sopenharmony_ci  char* buffer_;
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  bool full() const { return (capacity_ - length_) == 1; }
2131cb0ef41Sopenharmony_ci  int space() const { return capacity_ - length_; }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
2161cb0ef41Sopenharmony_ci};
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci}  // namespace internal
2191cb0ef41Sopenharmony_ci}  // namespace v8
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci#endif  // V8_STRINGS_STRING_STREAM_H_
222