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