Stream.cpp revision 353358
148905Srnordier//===-- Stream.cpp ----------------------------------------------*- C++ -*-===//
248905Srnordier//
348905Srnordier// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
448905Srnordier// See https://llvm.org/LICENSE.txt for license information.
548905Srnordier// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
648905Srnordier//
748905Srnordier//===----------------------------------------------------------------------===//
848905Srnordier
948905Srnordier#include "lldb/Utility/Stream.h"
1048905Srnordier
1148905Srnordier#include "lldb/Utility/Endian.h"
1248905Srnordier#include "lldb/Utility/VASPrintf.h"
1348905Srnordier#include "llvm/ADT/SmallString.h"
1448905Srnordier#include "llvm/Support/LEB128.h"
1548905Srnordier
1648905Srnordier#include <string>
1748905Srnordier
1848905Srnordier#include <inttypes.h>
1948905Srnordier#include <stddef.h>
2048905Srnordier
2148905Srnordierusing namespace lldb;
2248905Srnordierusing namespace lldb_private;
2348905Srnordier
2448905SrnordierStream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
2550479Speter    : m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order),
2648905Srnordier      m_indent_level(0), m_forwarder(*this) {}
2748905Srnordier
2848905SrnordierStream::Stream()
2979537Sru    : m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()),
3048905Srnordier      m_indent_level(0), m_forwarder(*this) {}
3148905Srnordier
3248905Srnordier// Destructor
3348905SrnordierStream::~Stream() {}
3468965Sru
3548905SrnordierByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
3668313Srnordier  ByteOrder old_byte_order = m_byte_order;
3748905Srnordier  m_byte_order = byte_order;
3848905Srnordier  return old_byte_order;
3948905Srnordier}
4048905Srnordier
4148905Srnordier// Put an offset "uval" out to the stream using the printf format in "format".
4248905Srnordiervoid Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
43131500Sru
44131500Sru// Put an SLEB128 "uval" out to the stream using the printf format in "format".
4548905Srnordiersize_t Stream::PutSLEB128(int64_t sval) {
4648905Srnordier  if (m_flags.Test(eBinary))
4748905Srnordier    return llvm::encodeSLEB128(sval, m_forwarder);
4848905Srnordier  else
4948905Srnordier    return Printf("0x%" PRIi64, sval);
5048905Srnordier}
5148905Srnordier
5248905Srnordier// Put an ULEB128 "uval" out to the stream using the printf format in "format".
53131500Srusize_t Stream::PutULEB128(uint64_t uval) {
54131500Sru  if (m_flags.Test(eBinary))
5548905Srnordier    return llvm::encodeULEB128(uval, m_forwarder);
5648905Srnordier  else
5748905Srnordier    return Printf("0x%" PRIx64, uval);
5848905Srnordier}
5948905Srnordier
6048905Srnordier// Print a raw NULL terminated C string to the stream.
6148905Srnordiersize_t Stream::PutCString(llvm::StringRef str) {
6248905Srnordier  size_t bytes_written = 0;
6368313Srnordier  bytes_written = Write(str.data(), str.size());
6448905Srnordier
6548905Srnordier  // when in binary mode, emit the NULL terminator
6648905Srnordier  if (m_flags.Test(eBinary))
6748905Srnordier    bytes_written += PutChar('\0');
6848905Srnordier  return bytes_written;
6948905Srnordier}
7048905Srnordier
7148905Srnordier// Print a double quoted NULL terminated C string to the stream using the
7248905Srnordier// printf format in "format".
7348905Srnordiervoid Stream::QuotedCString(const char *cstr, const char *format) {
7448905Srnordier  Printf(format, cstr);
7548905Srnordier}
7648905Srnordier
7748905Srnordier// Put an address "addr" out to the stream with optional prefix and suffix
7868313Srnordier// strings.
7968313Srnordiervoid Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
8068313Srnordier                     const char *suffix) {
8168313Srnordier  if (prefix == nullptr)
8268313Srnordier    prefix = "";
8368313Srnordier  if (suffix == nullptr)
8468313Srnordier    suffix = "";
8568313Srnordier  //    int addr_width = m_addr_size << 1;
8668313Srnordier  //    Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix);
8768313Srnordier  Printf("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, addr, suffix);
8848905Srnordier}
8948905Srnordier
9048905Srnordier// Put an address range out to the stream with optional prefix and suffix
9148905Srnordier// strings.
9248905Srnordiervoid Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr,
9348905Srnordier                          uint32_t addr_size, const char *prefix,
9448905Srnordier                          const char *suffix) {
9548905Srnordier  if (prefix && prefix[0])
9648905Srnordier    PutCString(prefix);
9748905Srnordier  Address(lo_addr, addr_size, "[");
9848905Srnordier  Address(hi_addr, addr_size, "-", ")");
9948905Srnordier  if (suffix && suffix[0])
10048905Srnordier    PutCString(suffix);
10148905Srnordier}
10248905Srnordier
10348905Srnordiersize_t Stream::PutChar(char ch) { return Write(&ch, 1); }
10448905Srnordier
10548905Srnordier// Print some formatted output to the stream.
10648905Srnordiersize_t Stream::Printf(const char *format, ...) {
10748905Srnordier  va_list args;
10848905Srnordier  va_start(args, format);
10948905Srnordier  size_t result = PrintfVarArg(format, args);
11048905Srnordier  va_end(args);
11148905Srnordier  return result;
11248905Srnordier}
11348905Srnordier
11448905Srnordier// Print some formatted output to the stream.
11548905Srnordiersize_t Stream::PrintfVarArg(const char *format, va_list args) {
11648905Srnordier  llvm::SmallString<1024> buf;
11748905Srnordier  VASprintf(buf, format, args);
11848905Srnordier
11948905Srnordier  // Include the NULL termination byte for binary output
12048905Srnordier  size_t length = buf.size();
12148905Srnordier  if (m_flags.Test(eBinary))
12248905Srnordier    ++length;
12348905Srnordier  return Write(buf.c_str(), length);
12448905Srnordier}
125140442Sru
126140442Sru// Print and End of Line character to the stream
12748905Srnordiersize_t Stream::EOL() { return PutChar('\n'); }
12848905Srnordier
12948905Srnordier// Indent the current line using the current indentation level and print an
13068313Srnordier// optional string following the indentation spaces.
13154868Sbillfsize_t Stream::Indent(const char *s) {
13248905Srnordier  return Printf("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
13348905Srnordier}
13448905Srnordier
13548905Srnordiersize_t Stream::Indent(llvm::StringRef str) {
13648905Srnordier  return Printf("%*.*s%s", m_indent_level, m_indent_level, "",
13748905Srnordier                str.str().c_str());
13848905Srnordier}
13948905Srnordier
14048905Srnordier// Stream a character "ch" out to this stream.
14148905SrnordierStream &Stream::operator<<(char ch) {
14248905Srnordier  PutChar(ch);
14348905Srnordier  return *this;
144}
145
146// Stream the NULL terminated C string out to this stream.
147Stream &Stream::operator<<(const char *s) {
148  Printf("%s", s);
149  return *this;
150}
151
152Stream &Stream::operator<<(llvm::StringRef str) {
153  Write(str.data(), str.size());
154  return *this;
155}
156
157// Stream the pointer value out to this stream.
158Stream &Stream::operator<<(const void *p) {
159  Printf("0x%.*tx", static_cast<int>(sizeof(const void *)) * 2, (ptrdiff_t)p);
160  return *this;
161}
162
163// Stream a uint8_t "uval" out to this stream.
164Stream &Stream::operator<<(uint8_t uval) {
165  PutHex8(uval);
166  return *this;
167}
168
169// Stream a uint16_t "uval" out to this stream.
170Stream &Stream::operator<<(uint16_t uval) {
171  PutHex16(uval, m_byte_order);
172  return *this;
173}
174
175// Stream a uint32_t "uval" out to this stream.
176Stream &Stream::operator<<(uint32_t uval) {
177  PutHex32(uval, m_byte_order);
178  return *this;
179}
180
181// Stream a uint64_t "uval" out to this stream.
182Stream &Stream::operator<<(uint64_t uval) {
183  PutHex64(uval, m_byte_order);
184  return *this;
185}
186
187// Stream a int8_t "sval" out to this stream.
188Stream &Stream::operator<<(int8_t sval) {
189  Printf("%i", static_cast<int>(sval));
190  return *this;
191}
192
193// Stream a int16_t "sval" out to this stream.
194Stream &Stream::operator<<(int16_t sval) {
195  Printf("%i", static_cast<int>(sval));
196  return *this;
197}
198
199// Stream a int32_t "sval" out to this stream.
200Stream &Stream::operator<<(int32_t sval) {
201  Printf("%i", static_cast<int>(sval));
202  return *this;
203}
204
205// Stream a int64_t "sval" out to this stream.
206Stream &Stream::operator<<(int64_t sval) {
207  Printf("%" PRIi64, sval);
208  return *this;
209}
210
211// Get the current indentation level
212int Stream::GetIndentLevel() const { return m_indent_level; }
213
214// Set the current indentation level
215void Stream::SetIndentLevel(int indent_level) { m_indent_level = indent_level; }
216
217// Increment the current indentation level
218void Stream::IndentMore(int amount) { m_indent_level += amount; }
219
220// Decrement the current indentation level
221void Stream::IndentLess(int amount) {
222  if (m_indent_level >= amount)
223    m_indent_level -= amount;
224  else
225    m_indent_level = 0;
226}
227
228// Get the address size in bytes
229uint32_t Stream::GetAddressByteSize() const { return m_addr_size; }
230
231// Set the address size in bytes
232void Stream::SetAddressByteSize(uint32_t addr_size) { m_addr_size = addr_size; }
233
234// The flags get accessor
235Flags &Stream::GetFlags() { return m_flags; }
236
237// The flags const get accessor
238const Flags &Stream::GetFlags() const { return m_flags; }
239
240// The byte order get accessor
241
242lldb::ByteOrder Stream::GetByteOrder() const { return m_byte_order; }
243
244size_t Stream::PrintfAsRawHex8(const char *format, ...) {
245  va_list args;
246  va_start(args, format);
247
248  llvm::SmallString<1024> buf;
249  VASprintf(buf, format, args);
250
251  ByteDelta delta(*this);
252  for (char C : buf)
253    _PutHex8(C, false);
254
255  va_end(args);
256
257  return *delta;
258}
259
260size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
261  ByteDelta delta(*this);
262  for (size_t i = 0; i < n; ++i)
263    _PutHex8(uvalue, false);
264  return *delta;
265}
266
267void Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
268  if (m_flags.Test(eBinary)) {
269    Write(&uvalue, 1);
270  } else {
271    if (add_prefix)
272      PutCString("0x");
273
274    static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5',
275                                               '6', '7', '8', '9', 'a', 'b',
276                                               'c', 'd', 'e', 'f'};
277    char nibble_chars[2];
278    nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
279    nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
280    Write(nibble_chars, sizeof(nibble_chars));
281  }
282}
283
284size_t Stream::PutHex8(uint8_t uvalue) {
285  ByteDelta delta(*this);
286  _PutHex8(uvalue, false);
287  return *delta;
288}
289
290size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) {
291  ByteDelta delta(*this);
292
293  if (byte_order == eByteOrderInvalid)
294    byte_order = m_byte_order;
295
296  if (byte_order == eByteOrderLittle) {
297    for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
298      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
299  } else {
300    for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
301      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
302  }
303  return *delta;
304}
305
306size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) {
307  ByteDelta delta(*this);
308
309  if (byte_order == eByteOrderInvalid)
310    byte_order = m_byte_order;
311
312  if (byte_order == eByteOrderLittle) {
313    for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
314      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
315  } else {
316    for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
317      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
318  }
319  return *delta;
320}
321
322size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) {
323  ByteDelta delta(*this);
324
325  if (byte_order == eByteOrderInvalid)
326    byte_order = m_byte_order;
327
328  if (byte_order == eByteOrderLittle) {
329    for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
330      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
331  } else {
332    for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
333      _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
334  }
335  return *delta;
336}
337
338size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
339                           lldb::ByteOrder byte_order) {
340  switch (byte_size) {
341  case 1:
342    return PutHex8(static_cast<uint8_t>(uvalue));
343  case 2:
344    return PutHex16(static_cast<uint16_t>(uvalue), byte_order);
345  case 4:
346    return PutHex32(static_cast<uint32_t>(uvalue), byte_order);
347  case 8:
348    return PutHex64(uvalue, byte_order);
349  }
350  return 0;
351}
352
353size_t Stream::PutPointer(void *ptr) {
354  return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(),
355                     endian::InlHostByteOrder());
356}
357
358size_t Stream::PutFloat(float f, ByteOrder byte_order) {
359  if (byte_order == eByteOrderInvalid)
360    byte_order = m_byte_order;
361
362  return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order);
363}
364
365size_t Stream::PutDouble(double d, ByteOrder byte_order) {
366  if (byte_order == eByteOrderInvalid)
367    byte_order = m_byte_order;
368
369  return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order);
370}
371
372size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) {
373  if (byte_order == eByteOrderInvalid)
374    byte_order = m_byte_order;
375
376  return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order);
377}
378
379size_t Stream::PutRawBytes(const void *s, size_t src_len,
380                           ByteOrder src_byte_order, ByteOrder dst_byte_order) {
381  ByteDelta delta(*this);
382
383  if (src_byte_order == eByteOrderInvalid)
384    src_byte_order = m_byte_order;
385
386  if (dst_byte_order == eByteOrderInvalid)
387    dst_byte_order = m_byte_order;
388
389  const uint8_t *src = static_cast<const uint8_t *>(s);
390  bool binary_was_set = m_flags.Test(eBinary);
391  if (!binary_was_set)
392    m_flags.Set(eBinary);
393  if (src_byte_order == dst_byte_order) {
394    for (size_t i = 0; i < src_len; ++i)
395      _PutHex8(src[i], false);
396  } else {
397    for (size_t i = src_len - 1; i < src_len; --i)
398      _PutHex8(src[i], false);
399  }
400  if (!binary_was_set)
401    m_flags.Clear(eBinary);
402
403  return *delta;
404}
405
406size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len,
407                                 ByteOrder src_byte_order,
408                                 ByteOrder dst_byte_order) {
409  ByteDelta delta(*this);
410  if (src_byte_order == eByteOrderInvalid)
411    src_byte_order = m_byte_order;
412
413  if (dst_byte_order == eByteOrderInvalid)
414    dst_byte_order = m_byte_order;
415
416  const uint8_t *src = static_cast<const uint8_t *>(s);
417  bool binary_is_set = m_flags.Test(eBinary);
418  m_flags.Clear(eBinary);
419  if (src_byte_order == dst_byte_order) {
420    for (size_t i = 0; i < src_len; ++i)
421      _PutHex8(src[i], false);
422  } else {
423    for (size_t i = src_len - 1; i < src_len; --i)
424      _PutHex8(src[i], false);
425  }
426  if (binary_is_set)
427    m_flags.Set(eBinary);
428
429  return *delta;
430}
431
432size_t Stream::PutStringAsRawHex8(llvm::StringRef s) {
433  ByteDelta delta(*this);
434  bool binary_is_set = m_flags.Test(eBinary);
435  m_flags.Clear(eBinary);
436  for (char c : s)
437    _PutHex8(c, false);
438  if (binary_is_set)
439    m_flags.Set(eBinary);
440  return *delta;
441}
442