1 | //===-- Stream.h ------------------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_UTILITY_STREAM_H |
10 | #define LLDB_UTILITY_STREAM_H |
11 | |
12 | #include "lldb/Utility/Flags.h" |
13 | #include "lldb/lldb-defines.h" |
14 | #include "lldb/lldb-enumerations.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/Support/FormatVariadic.h" |
17 | #include "llvm/Support/raw_ostream.h" |
18 | |
19 | #include <cstdarg> |
20 | #include <cstddef> |
21 | #include <cstdint> |
22 | #include <type_traits> |
23 | |
24 | namespace lldb_private { |
25 | |
26 | /// \class Stream Stream.h "lldb/Utility/Stream.h" |
27 | /// A stream class that can stream formatted output to a file. |
28 | class Stream { |
29 | public: |
30 | /// \a m_flags bit values. |
31 | enum { |
32 | eBinary = (1 << 0) ///< Get and put data as binary instead of as the default |
33 | /// string mode. |
34 | }; |
35 | |
36 | /// Struct to store information for color highlighting in the stream. |
37 | struct HighlightSettings { |
38 | llvm::StringRef pattern; ///< Regex pattern for highlighting. |
39 | llvm::StringRef prefix; ///< ANSI color code to start colorization. |
40 | llvm::StringRef suffix; ///< ANSI color code to end colorization. |
41 | |
42 | HighlightSettings(llvm::StringRef p, llvm::StringRef pre, |
43 | llvm::StringRef suf) |
44 | : pattern(p), prefix(pre), suffix(suf) {} |
45 | }; |
46 | |
47 | /// Utility class for counting the bytes that were written to a stream in a |
48 | /// certain time span. |
49 | /// |
50 | /// \example |
51 | /// ByteDelta delta(*this); |
52 | /// WriteDataToStream("foo"); |
53 | /// return *delta; |
54 | class ByteDelta { |
55 | Stream *m_stream; |
56 | /// Bytes we have written so far when ByteDelta was created. |
57 | size_t m_start; |
58 | |
59 | public: |
60 | ByteDelta(Stream &s) : m_stream(&s), m_start(s.GetWrittenBytes()) {} |
61 | /// Returns the number of bytes written to the given Stream since this |
62 | /// ByteDelta object was created. |
63 | size_t operator*() const { return m_stream->GetWrittenBytes() - m_start; } |
64 | }; |
65 | |
66 | /// Construct with flags and address size and byte order. |
67 | /// |
68 | /// Construct with dump flags \a flags and the default address size. \a |
69 | /// flags can be any of the above enumeration logical OR'ed together. |
70 | Stream(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order, |
71 | bool colors = false); |
72 | |
73 | /// Construct a default Stream, not binary, host byte order and host addr |
74 | /// size. |
75 | /// |
76 | Stream(bool colors = false); |
77 | |
78 | // FIXME: Streams should not be copyable. |
79 | Stream(const Stream &other) : m_forwarder(*this) { (*this) = other; } |
80 | |
81 | Stream &operator=(const Stream &rhs) { |
82 | m_flags = rhs.m_flags; |
83 | m_addr_size = rhs.m_addr_size; |
84 | m_byte_order = rhs.m_byte_order; |
85 | m_indent_level = rhs.m_indent_level; |
86 | return *this; |
87 | } |
88 | |
89 | /// Destructor |
90 | virtual ~Stream(); |
91 | |
92 | // Subclasses must override these methods |
93 | |
94 | /// Flush the stream. |
95 | /// |
96 | /// Subclasses should flush the stream to make any output appear if the |
97 | /// stream has any buffering. |
98 | virtual void Flush() = 0; |
99 | |
100 | /// Output character bytes to the stream. |
101 | /// |
102 | /// Appends \a src_len characters from the buffer \a src to the stream. |
103 | /// |
104 | /// \param[in] src |
105 | /// A buffer containing at least \a src_len bytes of data. |
106 | /// |
107 | /// \param[in] src_len |
108 | /// A number of bytes to append to the stream. |
109 | /// |
110 | /// \return |
111 | /// The number of bytes that were appended to the stream. |
112 | size_t Write(const void *src, size_t src_len) { |
113 | size_t appended_byte_count = WriteImpl(src, src_len); |
114 | m_bytes_written += appended_byte_count; |
115 | return appended_byte_count; |
116 | } |
117 | |
118 | size_t GetWrittenBytes() const { return m_bytes_written; } |
119 | |
120 | // Member functions |
121 | size_t PutChar(char ch); |
122 | |
123 | /// Set the byte_order value. |
124 | /// |
125 | /// Sets the byte order of the data to extract. Extracted values will be |
126 | /// swapped if necessary when decoding. |
127 | /// |
128 | /// \param[in] byte_order |
129 | /// The byte order value to use when extracting data. |
130 | /// |
131 | /// \return |
132 | /// The old byte order value. |
133 | lldb::ByteOrder SetByteOrder(lldb::ByteOrder byte_order); |
134 | |
135 | /// Format a C string from a printf style format and variable arguments and |
136 | /// encode and append the resulting C string as hex bytes. |
137 | /// |
138 | /// \param[in] format |
139 | /// A printf style format string. |
140 | /// |
141 | /// \param[in] ... |
142 | /// Any additional arguments needed for the printf format string. |
143 | /// |
144 | /// \return |
145 | /// The number of bytes that were appended to the stream. |
146 | size_t PrintfAsRawHex8(const char *format, ...) |
147 | __attribute__((__format__(__printf__, 2, 3))); |
148 | |
149 | /// Append an uint8_t value in the hexadecimal format to the stream. |
150 | /// |
151 | /// \param[in] uvalue |
152 | /// The value to append. |
153 | /// |
154 | /// \return |
155 | /// The number of bytes that were appended to the stream. |
156 | size_t PutHex8(uint8_t uvalue); |
157 | |
158 | size_t PutNHex8(size_t n, uint8_t uvalue); |
159 | |
160 | size_t PutHex16(uint16_t uvalue, |
161 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
162 | |
163 | size_t PutHex32(uint32_t uvalue, |
164 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
165 | |
166 | size_t PutHex64(uint64_t uvalue, |
167 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
168 | |
169 | size_t PutMaxHex64(uint64_t uvalue, size_t byte_size, |
170 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
171 | size_t PutFloat(float f, |
172 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
173 | |
174 | size_t PutDouble(double d, |
175 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
176 | |
177 | size_t PutLongDouble(long double ld, |
178 | lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); |
179 | |
180 | size_t PutPointer(void *ptr); |
181 | |
182 | // Append \a src_len bytes from \a src to the stream as hex characters (two |
183 | // ascii characters per byte of input data) |
184 | size_t |
185 | PutBytesAsRawHex8(const void *src, size_t src_len, |
186 | lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid, |
187 | lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid); |
188 | |
189 | // Append \a src_len bytes from \a s to the stream as binary data. |
190 | size_t PutRawBytes(const void *s, size_t src_len, |
191 | lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid, |
192 | lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid); |
193 | |
194 | size_t PutStringAsRawHex8(llvm::StringRef s); |
195 | |
196 | /// Output a NULL terminated C string \a cstr to the stream \a s. |
197 | /// |
198 | /// \param[in] cstr |
199 | /// A NULL terminated C string. |
200 | /// |
201 | /// \return |
202 | /// A reference to this class so multiple things can be streamed |
203 | /// in one statement. |
204 | Stream &operator<<(const char *cstr); |
205 | |
206 | Stream &operator<<(llvm::StringRef str); |
207 | |
208 | /// Output a pointer value \a p to the stream \a s. |
209 | /// |
210 | /// \param[in] p |
211 | /// A void pointer. |
212 | /// |
213 | /// \return |
214 | /// A reference to this class so multiple things can be streamed |
215 | /// in one statement. |
216 | Stream &operator<<(const void *p); |
217 | |
218 | /// Output a character \a ch to the stream \a s. |
219 | /// |
220 | /// \param[in] ch |
221 | /// A printable character value. |
222 | /// |
223 | /// \return |
224 | /// A reference to this class so multiple things can be streamed |
225 | /// in one statement. |
226 | Stream &operator<<(char ch); |
227 | |
228 | Stream &operator<<(uint8_t uval) = delete; |
229 | Stream &operator<<(uint16_t uval) = delete; |
230 | Stream &operator<<(uint32_t uval) = delete; |
231 | Stream &operator<<(uint64_t uval) = delete; |
232 | Stream &operator<<(int8_t sval) = delete; |
233 | Stream &operator<<(int16_t sval) = delete; |
234 | Stream &operator<<(int32_t sval) = delete; |
235 | Stream &operator<<(int64_t sval) = delete; |
236 | |
237 | /// Output a C string to the stream. |
238 | /// |
239 | /// Print a C string \a cstr to the stream. |
240 | /// |
241 | /// \param[in] cstr |
242 | /// The string to be output to the stream. |
243 | size_t PutCString(llvm::StringRef cstr); |
244 | |
245 | /// Output a C string to the stream with color highlighting. |
246 | /// |
247 | /// Print a C string \a text to the stream, applying color highlighting to |
248 | /// the portions of the string that match the regex pattern \a pattern. The |
249 | /// pattern is matched as many times as possible throughout the string. If \a |
250 | /// pattern is nullptr, then no highlighting is applied. |
251 | /// |
252 | /// The highlighting is applied by enclosing the matching text in ANSI color |
253 | /// codes. The \a prefix parameter specifies the ANSI code to start the color |
254 | /// (the standard value is assumed to be 'ansi.fg.red', representing red |
255 | /// foreground), and the \a suffix parameter specifies the ANSI code to end |
256 | /// the color (the standard value is assumed to be 'ansi.normal', resetting to |
257 | /// default text style). These constants should be defined appropriately in |
258 | /// your environment. |
259 | /// |
260 | /// \param[in] text |
261 | /// The string to be output to the stream. |
262 | /// |
263 | /// \param[in] pattern |
264 | /// The regex pattern to match against the \a text string. Portions of \a |
265 | /// text matching this pattern will be colorized. If this parameter is |
266 | /// nullptr, highlighting is not performed. |
267 | /// \param[in] prefix |
268 | /// The ANSI color code to start colorization. This is |
269 | /// environment-dependent. |
270 | /// \param[in] suffix |
271 | /// The ANSI color code to end colorization. This is |
272 | /// environment-dependent. |
273 | |
274 | void PutCStringColorHighlighted( |
275 | llvm::StringRef text, |
276 | std::optional<HighlightSettings> settings = std::nullopt); |
277 | |
278 | /// Output and End of Line character to the stream. |
279 | size_t EOL(); |
280 | |
281 | /// Get the address size in bytes. |
282 | /// |
283 | /// \return |
284 | /// The size of an address in bytes that is used when outputting |
285 | /// address and pointer values to the stream. |
286 | uint32_t GetAddressByteSize() const; |
287 | |
288 | /// The flags accessor. |
289 | /// |
290 | /// \return |
291 | /// A reference to the Flags member variable. |
292 | Flags &GetFlags(); |
293 | |
294 | /// The flags const accessor. |
295 | /// |
296 | /// \return |
297 | /// A const reference to the Flags member variable. |
298 | const Flags &GetFlags() const; |
299 | |
300 | //// The byte order accessor. |
301 | //// |
302 | //// \return |
303 | //// The byte order. |
304 | lldb::ByteOrder GetByteOrder() const; |
305 | |
306 | /// Get the current indentation level. |
307 | /// |
308 | /// \return |
309 | /// The current indentation level. |
310 | unsigned GetIndentLevel() const; |
311 | |
312 | /// Indent the current line in the stream. |
313 | /// |
314 | /// Indent the current line using the current indentation level and print an |
315 | /// optional string following the indentation spaces. |
316 | /// |
317 | /// \param[in] s |
318 | /// A string to print following the indentation. |
319 | size_t Indent(llvm::StringRef s = "" ); |
320 | |
321 | /// Decrement the current indentation level. |
322 | void IndentLess(unsigned amount = 2); |
323 | |
324 | /// Increment the current indentation level. |
325 | void IndentMore(unsigned amount = 2); |
326 | |
327 | /// Output an offset value. |
328 | /// |
329 | /// Put an offset \a uval out to the stream using the printf format in \a |
330 | /// format. |
331 | /// |
332 | /// \param[in] offset |
333 | /// The offset value. |
334 | /// |
335 | /// \param[in] format |
336 | /// The printf style format to use when outputting the offset. |
337 | void Offset(uint32_t offset, const char *format = "0x%8.8x: " ); |
338 | |
339 | /// Output printf formatted output to the stream. |
340 | /// |
341 | /// Print some formatted output to the stream. |
342 | /// |
343 | /// \param[in] format |
344 | /// A printf style format string. |
345 | /// |
346 | /// \param[in] ... |
347 | /// Variable arguments that are needed for the printf style |
348 | /// format string \a format. |
349 | size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); |
350 | |
351 | size_t PrintfVarArg(const char *format, va_list args); |
352 | |
353 | template <typename... Args> void Format(const char *format, Args &&... args) { |
354 | PutCString(cstr: llvm::formatv(format, std::forward<Args>(args)...).str()); |
355 | } |
356 | |
357 | /// Output a quoted C string value to the stream. |
358 | /// |
359 | /// Print a double quoted NULL terminated C string to the stream using the |
360 | /// printf format in \a format. |
361 | /// |
362 | /// \param[in] cstr |
363 | /// A NULL terminated C string value. |
364 | /// |
365 | /// \param[in] format |
366 | /// The optional C string format that can be overridden. |
367 | void QuotedCString(const char *cstr, const char *format = "\"%s\"" ); |
368 | |
369 | /// Set the address size in bytes. |
370 | /// |
371 | /// \param[in] addr_size |
372 | /// The new size in bytes of an address to use when outputting |
373 | /// address and pointer values. |
374 | void SetAddressByteSize(uint32_t addr_size); |
375 | |
376 | /// Set the current indentation level. |
377 | /// |
378 | /// \param[in] level |
379 | /// The new indentation level. |
380 | void SetIndentLevel(unsigned level); |
381 | |
382 | /// Output a SLEB128 number to the stream. |
383 | /// |
384 | /// Put an SLEB128 \a uval out to the stream using the printf format in \a |
385 | /// format. |
386 | /// |
387 | /// \param[in] uval |
388 | /// A uint64_t value that was extracted as a SLEB128 value. |
389 | size_t PutSLEB128(int64_t uval); |
390 | |
391 | /// Output a ULEB128 number to the stream. |
392 | /// |
393 | /// Put an ULEB128 \a uval out to the stream using the printf format in \a |
394 | /// format. |
395 | /// |
396 | /// \param[in] uval |
397 | /// A uint64_t value that was extracted as a ULEB128 value. |
398 | size_t PutULEB128(uint64_t uval); |
399 | |
400 | /// Returns a raw_ostream that forwards the data to this Stream object. |
401 | llvm::raw_ostream &AsRawOstream() { |
402 | return m_forwarder; |
403 | } |
404 | |
405 | protected: |
406 | // Member variables |
407 | Flags m_flags; ///< Dump flags. |
408 | uint32_t m_addr_size = 4; ///< Size of an address in bytes. |
409 | lldb::ByteOrder |
410 | m_byte_order; ///< Byte order to use when encoding scalar types. |
411 | unsigned m_indent_level = 0; ///< Indention level. |
412 | std::size_t m_bytes_written = 0; ///< Number of bytes written so far. |
413 | |
414 | void _PutHex8(uint8_t uvalue, bool add_prefix); |
415 | |
416 | /// Output character bytes to the stream. |
417 | /// |
418 | /// Appends \a src_len characters from the buffer \a src to the stream. |
419 | /// |
420 | /// \param[in] src |
421 | /// A buffer containing at least \a src_len bytes of data. |
422 | /// |
423 | /// \param[in] src_len |
424 | /// A number of bytes to append to the stream. |
425 | /// |
426 | /// \return |
427 | /// The number of bytes that were appended to the stream. |
428 | virtual size_t WriteImpl(const void *src, size_t src_len) = 0; |
429 | |
430 | /// \class RawOstreamForward Stream.h "lldb/Utility/Stream.h" |
431 | /// This is a wrapper class that exposes a raw_ostream interface that just |
432 | /// forwards to an LLDB stream, allowing to reuse LLVM algorithms that take |
433 | /// a raw_ostream within the LLDB code base. |
434 | class RawOstreamForward : public llvm::raw_ostream { |
435 | // Note: This stream must *not* maintain its own buffer, but instead |
436 | // directly write everything to the internal Stream class. Without this, |
437 | // we would run into the problem that the Stream written byte count would |
438 | // differ from the actually written bytes by the size of the internal |
439 | // raw_ostream buffer. |
440 | |
441 | Stream &m_target; |
442 | void write_impl(const char *Ptr, size_t Size) override { |
443 | m_target.Write(src: Ptr, src_len: Size); |
444 | } |
445 | |
446 | uint64_t current_pos() const override { |
447 | return m_target.GetWrittenBytes(); |
448 | } |
449 | |
450 | public: |
451 | RawOstreamForward(Stream &target, bool colors = false) |
452 | : llvm::raw_ostream(/*unbuffered*/ true), m_target(target) { |
453 | enable_colors(enable: colors); |
454 | } |
455 | }; |
456 | RawOstreamForward m_forwarder; |
457 | }; |
458 | |
459 | /// Output an address value to this stream. |
460 | /// |
461 | /// Put an address \a addr out to the stream with optional \a prefix and \a |
462 | /// suffix strings. |
463 | /// |
464 | /// \param[in] s |
465 | /// The output stream. |
466 | /// |
467 | /// \param[in] addr |
468 | /// An address value. |
469 | /// |
470 | /// \param[in] addr_size |
471 | /// Size in bytes of the address, used for formatting. |
472 | /// |
473 | /// \param[in] prefix |
474 | /// A prefix C string. If nullptr, no prefix will be output. |
475 | /// |
476 | /// \param[in] suffix |
477 | /// A suffix C string. If nullptr, no suffix will be output. |
478 | void DumpAddress(llvm::raw_ostream &s, uint64_t addr, uint32_t addr_size, |
479 | const char *prefix = nullptr, const char *suffix = nullptr); |
480 | |
481 | /// Output an address range to this stream. |
482 | /// |
483 | /// Put an address range \a lo_addr - \a hi_addr out to the stream with |
484 | /// optional \a prefix and \a suffix strings. |
485 | /// |
486 | /// \param[in] s |
487 | /// The output stream. |
488 | /// |
489 | /// \param[in] lo_addr |
490 | /// The start address of the address range. |
491 | /// |
492 | /// \param[in] hi_addr |
493 | /// The end address of the address range. |
494 | /// |
495 | /// \param[in] addr_size |
496 | /// Size in bytes of the address, used for formatting. |
497 | /// |
498 | /// \param[in] prefix |
499 | /// A prefix C string. If nullptr, no prefix will be output. |
500 | /// |
501 | /// \param[in] suffix |
502 | /// A suffix C string. If nullptr, no suffix will be output. |
503 | void DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr, uint64_t hi_addr, |
504 | uint32_t addr_size, const char *prefix = nullptr, |
505 | const char *suffix = nullptr); |
506 | |
507 | } // namespace lldb_private |
508 | |
509 | #endif // LLDB_UTILITY_STREAM_H |
510 | |