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