1// Copyright 2014 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_STRING_STREAM_H_
6#define V8_STRING_STREAM_H_
7
8#include "src/allocation.h"
9#include "src/handles.h"
10#include "src/vector.h"
11
12namespace v8 {
13namespace internal {
14
15// Forward declarations.
16class ByteArray;
17
18class StringAllocator {
19 public:
20  virtual ~StringAllocator() { }
21  // Allocate a number of bytes.
22  virtual char* allocate(unsigned bytes) = 0;
23  // Allocate a larger number of bytes and copy the old buffer to the new one.
24  // bytes is an input and output parameter passing the old size of the buffer
25  // and returning the new size.  If allocation fails then we return the old
26  // buffer and do not increase the size.
27  virtual char* grow(unsigned* bytes) = 0;
28};
29
30
31// Normal allocator uses new[] and delete[].
32class HeapStringAllocator final : public StringAllocator {
33 public:
34  ~HeapStringAllocator() { DeleteArray(space_); }
35  char* allocate(unsigned bytes) override;
36  char* grow(unsigned* bytes) override;
37
38 private:
39  char* space_;
40};
41
42
43class FixedStringAllocator final : public StringAllocator {
44 public:
45  FixedStringAllocator(char* buffer, unsigned length)
46      : buffer_(buffer), length_(length) {}
47  ~FixedStringAllocator() override{};
48  char* allocate(unsigned bytes) override;
49  char* grow(unsigned* bytes) override;
50
51 private:
52  char* buffer_;
53  unsigned length_;
54  DISALLOW_COPY_AND_ASSIGN(FixedStringAllocator);
55};
56
57class StringStream final {
58  class FmtElm final {
59   public:
60    FmtElm(int value) : FmtElm(INT) {  // NOLINT
61      data_.u_int_ = value;
62    }
63    explicit FmtElm(double value) : FmtElm(DOUBLE) {  // NOLINT
64      data_.u_double_ = value;
65    }
66    FmtElm(const char* value) : FmtElm(C_STR) {  // NOLINT
67      data_.u_c_str_ = value;
68    }
69    FmtElm(const Vector<const uc16>& value) : FmtElm(LC_STR) {  // NOLINT
70      data_.u_lc_str_ = &value;
71    }
72    FmtElm(Object* value) : FmtElm(OBJ) {  // NOLINT
73      data_.u_obj_ = value;
74    }
75    FmtElm(Handle<Object> value) : FmtElm(HANDLE) {  // NOLINT
76      data_.u_handle_ = value.location();
77    }
78    FmtElm(void* value) : FmtElm(POINTER) {  // NOLINT
79      data_.u_pointer_ = value;
80    }
81
82   private:
83    friend class StringStream;
84    enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };
85
86#ifdef DEBUG
87    Type type_;
88    explicit FmtElm(Type type) : type_(type) {}
89#else
90    explicit FmtElm(Type) {}
91#endif
92
93    union {
94      int u_int_;
95      double u_double_;
96      const char* u_c_str_;
97      const Vector<const uc16>* u_lc_str_;
98      Object* u_obj_;
99      Object** u_handle_;
100      void* u_pointer_;
101    } data_;
102  };
103
104 public:
105  enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
106  StringStream(StringAllocator* allocator,
107               ObjectPrintMode object_print_mode = kPrintObjectVerbose)
108      : allocator_(allocator),
109        object_print_mode_(object_print_mode),
110        capacity_(kInitialCapacity),
111        length_(0),
112        buffer_(allocator_->allocate(kInitialCapacity)) {
113    buffer_[0] = 0;
114  }
115
116  bool Put(char c);
117  bool Put(String* str);
118  bool Put(String* str, int start, int end);
119  void Add(const char* format) { Add(CStrVector(format)); }
120  void Add(Vector<const char> format) { Add(format, Vector<FmtElm>()); }
121
122  template <typename... Args>
123  void Add(const char* format, Args... args) {
124    Add(CStrVector(format), args...);
125  }
126
127  template <typename... Args>
128  void Add(Vector<const char> format, Args... args) {
129    FmtElm elems[]{args...};
130    Add(format, ArrayVector(elems));
131  }
132
133  // Getting the message out.
134  void OutputToFile(FILE* out);
135  void OutputToStdOut() { OutputToFile(stdout); }
136  void Log(Isolate* isolate);
137  Handle<String> ToString(Isolate* isolate);
138  std::unique_ptr<char[]> ToCString() const;
139  int length() const { return length_; }
140
141  // Object printing support.
142  void PrintName(Object* o);
143  void PrintFixedArray(FixedArray* array, unsigned int limit);
144  void PrintByteArray(ByteArray* ba);
145  void PrintUsingMap(JSObject* js_object);
146  void PrintPrototype(JSFunction* fun, Object* receiver);
147  void PrintSecurityTokenIfChanged(Object* function);
148  // NOTE: Returns the code in the output parameter.
149  void PrintFunction(Object* function, Object* receiver, Code** code);
150
151  // Reset the stream.
152  void Reset() {
153    length_ = 0;
154    buffer_[0] = 0;
155  }
156
157  // Mentioned object cache support.
158  void PrintMentionedObjectCache(Isolate* isolate);
159  static void ClearMentionedObjectCache(Isolate* isolate);
160#ifdef DEBUG
161  bool IsMentionedObjectCacheClear(Isolate* isolate);
162#endif
163
164  static const int kInitialCapacity = 16;
165
166 private:
167  void Add(Vector<const char> format, Vector<FmtElm> elms);
168  void PrintObject(Object* obj);
169
170  StringAllocator* allocator_;
171  ObjectPrintMode object_print_mode_;
172  unsigned capacity_;
173  unsigned length_;  // does not include terminating 0-character
174  char* buffer_;
175
176  bool full() const { return (capacity_ - length_) == 1; }
177  int space() const { return capacity_ - length_; }
178
179  DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
180};
181
182}  // namespace internal
183}  // namespace v8
184
185#endif  // V8_STRING_STREAM_H_
186