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