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_OSTREAMS_H_ |
6 | #define V8_OSTREAMS_H_ |
7 | |
8 | #include <cstddef> |
9 | #include <cstdio> |
10 | #include <cstring> |
11 | #include <ostream> // NOLINT |
12 | #include <streambuf> |
13 | |
14 | #include "include/v8config.h" |
15 | #include "src/base/macros.h" |
16 | #include "src/globals.h" |
17 | |
18 | namespace v8 { |
19 | namespace internal { |
20 | |
21 | class V8_EXPORT_PRIVATE OFStreamBase : public std::streambuf { |
22 | public: |
23 | explicit OFStreamBase(FILE* f); |
24 | ~OFStreamBase() override = default; |
25 | |
26 | protected: |
27 | FILE* const f_; |
28 | |
29 | int sync() override; |
30 | int_type overflow(int_type c) override; |
31 | std::streamsize xsputn(const char* s, std::streamsize n) override; |
32 | }; |
33 | |
34 | // Output buffer and stream writing into debugger's command window. |
35 | class V8_EXPORT_PRIVATE DbgStreamBuf : public std::streambuf { |
36 | public: |
37 | DbgStreamBuf(); |
38 | ~DbgStreamBuf(); |
39 | |
40 | private: |
41 | int sync() override; |
42 | int overflow(int c) override; |
43 | |
44 | char data_[256]; |
45 | }; |
46 | |
47 | class DbgStdoutStream : public std::ostream { |
48 | public: |
49 | DbgStdoutStream(); |
50 | ~DbgStdoutStream() = default; |
51 | |
52 | private: |
53 | DbgStreamBuf streambuf_; |
54 | }; |
55 | |
56 | // An output stream writing to a file. |
57 | class V8_EXPORT_PRIVATE OFStream : public std::ostream { |
58 | public: |
59 | explicit OFStream(FILE* f); |
60 | ~OFStream() override = default; |
61 | |
62 | private: |
63 | OFStreamBase buf_; |
64 | }; |
65 | |
66 | #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) |
67 | class V8_EXPORT_PRIVATE AndroidLogStream : public std::streambuf { |
68 | public: |
69 | virtual ~AndroidLogStream(); |
70 | |
71 | protected: |
72 | std::streamsize xsputn(const char* s, std::streamsize n) override; |
73 | |
74 | private: |
75 | std::string line_buffer_; |
76 | }; |
77 | |
78 | class StdoutStream : public std::ostream { |
79 | public: |
80 | StdoutStream() : std::ostream(&stream_) {} |
81 | |
82 | private: |
83 | AndroidLogStream stream_; |
84 | }; |
85 | #else |
86 | class StdoutStream : public OFStream { |
87 | public: |
88 | StdoutStream() : OFStream(stdout) {} |
89 | }; |
90 | #endif |
91 | |
92 | // Wrappers to disambiguate uint16_t and uc16. |
93 | struct AsUC16 { |
94 | explicit AsUC16(uint16_t v) : value(v) {} |
95 | uint16_t value; |
96 | }; |
97 | |
98 | |
99 | struct AsUC32 { |
100 | explicit AsUC32(int32_t v) : value(v) {} |
101 | int32_t value; |
102 | }; |
103 | |
104 | |
105 | struct AsReversiblyEscapedUC16 { |
106 | explicit AsReversiblyEscapedUC16(uint16_t v) : value(v) {} |
107 | uint16_t value; |
108 | }; |
109 | |
110 | struct AsEscapedUC16ForJSON { |
111 | explicit AsEscapedUC16ForJSON(uint16_t v) : value(v) {} |
112 | uint16_t value; |
113 | }; |
114 | |
115 | // Output the given value as hex, with a minimum width and optional prefix (0x). |
116 | // E.g. AsHex(23, 3, true) produces "0x017". Produces an empty string if both |
117 | // {min_width} and the value are 0. |
118 | struct AsHex { |
119 | explicit AsHex(uint64_t v, uint8_t min_width = 1, bool with_prefix = false) |
120 | : value(v), min_width(min_width), with_prefix(with_prefix) {} |
121 | uint64_t value; |
122 | uint8_t min_width; |
123 | bool with_prefix; |
124 | |
125 | static AsHex Address(Address a) { |
126 | return AsHex(a, kSystemPointerHexDigits, true); |
127 | } |
128 | }; |
129 | |
130 | // Output the given value as hex, separated in individual bytes. |
131 | // E.g. AsHexBytes(0x231712, 4) produces "12 17 23 00" if output as little |
132 | // endian (default), and "00 23 17 12" as big endian. Produces an empty string |
133 | // if both {min_bytes} and the value are 0. |
134 | struct AsHexBytes { |
135 | enum ByteOrder { kLittleEndian, kBigEndian }; |
136 | explicit AsHexBytes(uint64_t v, uint8_t min_bytes = 1, |
137 | ByteOrder byte_order = kLittleEndian) |
138 | : value(v), min_bytes(min_bytes), byte_order(byte_order) {} |
139 | uint64_t value; |
140 | uint8_t min_bytes; |
141 | ByteOrder byte_order; |
142 | }; |
143 | |
144 | template <typename T> |
145 | struct PrintIteratorRange { |
146 | T start; |
147 | T end; |
148 | PrintIteratorRange(T start, T end) : start(start), end(end) {} |
149 | }; |
150 | |
151 | // Print any collection which can be iterated via std::begin and std::end. |
152 | // {Iterator} is the common type of {std::begin} and {std::end} called on a |
153 | // {const T&}. This function is only instantiable if that type exists. |
154 | template <typename T, typename Iterator = typename std::common_type< |
155 | decltype(std::begin(std::declval<const T&>())), |
156 | decltype(std::end(std::declval<const T&>()))>::type> |
157 | PrintIteratorRange<Iterator> PrintCollection(const T& collection) { |
158 | return {std::begin(collection), std::end(collection)}; |
159 | } |
160 | |
161 | // Writes the given character to the output escaping everything outside of |
162 | // printable/space ASCII range. Additionally escapes '\' making escaping |
163 | // reversible. |
164 | std::ostream& operator<<(std::ostream& os, const AsReversiblyEscapedUC16& c); |
165 | |
166 | // Same as AsReversiblyEscapedUC16 with additional escaping of \n, \r, " and '. |
167 | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, |
168 | const AsEscapedUC16ForJSON& c); |
169 | |
170 | // Writes the given character to the output escaping everything outside |
171 | // of printable ASCII range. |
172 | std::ostream& operator<<(std::ostream& os, const AsUC16& c); |
173 | |
174 | // Writes the given character to the output escaping everything outside |
175 | // of printable ASCII range. |
176 | std::ostream& operator<<(std::ostream& os, const AsUC32& c); |
177 | |
178 | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const AsHex& v); |
179 | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, |
180 | const AsHexBytes& v); |
181 | |
182 | template <typename T> |
183 | std::ostream& operator<<(std::ostream& os, const PrintIteratorRange<T>& range) { |
184 | const char* comma = "" ; |
185 | os << "[" ; |
186 | for (T it = range.start; it != range.end; ++it, comma = ", " ) { |
187 | os << comma << *it; |
188 | } |
189 | os << "]" ; |
190 | return os; |
191 | } |
192 | |
193 | } // namespace internal |
194 | } // namespace v8 |
195 | |
196 | #endif // V8_OSTREAMS_H_ |
197 | |