xref: /freebsd/contrib/llvm-project/lldb/source/Utility/Stream.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===-- Stream.cpp --------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
120b57cec5SDimitry Andric #include "lldb/Utility/VASPrintf.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
14480093f4SDimitry Andric #include "llvm/Support/Format.h"
150b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include <string>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include <inttypes.h>
200b57cec5SDimitry Andric #include <stddef.h>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace lldb;
230b57cec5SDimitry Andric using namespace lldb_private;
240b57cec5SDimitry Andric 
25*5ffd83dbSDimitry Andric Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order,
26*5ffd83dbSDimitry Andric                bool colors)
270b57cec5SDimitry Andric     : m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order),
28*5ffd83dbSDimitry Andric       m_indent_level(0), m_forwarder(*this, colors) {}
290b57cec5SDimitry Andric 
30*5ffd83dbSDimitry Andric Stream::Stream(bool colors)
310b57cec5SDimitry Andric     : m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()),
32*5ffd83dbSDimitry Andric       m_indent_level(0), m_forwarder(*this, colors) {}
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric // Destructor
350b57cec5SDimitry Andric Stream::~Stream() {}
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
380b57cec5SDimitry Andric   ByteOrder old_byte_order = m_byte_order;
390b57cec5SDimitry Andric   m_byte_order = byte_order;
400b57cec5SDimitry Andric   return old_byte_order;
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric // Put an offset "uval" out to the stream using the printf format in "format".
440b57cec5SDimitry Andric void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric // Put an SLEB128 "uval" out to the stream using the printf format in "format".
470b57cec5SDimitry Andric size_t Stream::PutSLEB128(int64_t sval) {
480b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
490b57cec5SDimitry Andric     return llvm::encodeSLEB128(sval, m_forwarder);
500b57cec5SDimitry Andric   else
510b57cec5SDimitry Andric     return Printf("0x%" PRIi64, sval);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric // Put an ULEB128 "uval" out to the stream using the printf format in "format".
550b57cec5SDimitry Andric size_t Stream::PutULEB128(uint64_t uval) {
560b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
570b57cec5SDimitry Andric     return llvm::encodeULEB128(uval, m_forwarder);
580b57cec5SDimitry Andric   else
590b57cec5SDimitry Andric     return Printf("0x%" PRIx64, uval);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric // Print a raw NULL terminated C string to the stream.
630b57cec5SDimitry Andric size_t Stream::PutCString(llvm::StringRef str) {
640b57cec5SDimitry Andric   size_t bytes_written = 0;
650b57cec5SDimitry Andric   bytes_written = Write(str.data(), str.size());
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   // when in binary mode, emit the NULL terminator
680b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
690b57cec5SDimitry Andric     bytes_written += PutChar('\0');
700b57cec5SDimitry Andric   return bytes_written;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric // Print a double quoted NULL terminated C string to the stream using the
740b57cec5SDimitry Andric // printf format in "format".
750b57cec5SDimitry Andric void Stream::QuotedCString(const char *cstr, const char *format) {
760b57cec5SDimitry Andric   Printf(format, cstr);
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // Put an address "addr" out to the stream with optional prefix and suffix
800b57cec5SDimitry Andric // strings.
81480093f4SDimitry Andric void lldb_private::DumpAddress(llvm::raw_ostream &s, uint64_t addr,
82480093f4SDimitry Andric                                uint32_t addr_size, const char *prefix,
830b57cec5SDimitry Andric                                const char *suffix) {
840b57cec5SDimitry Andric   if (prefix == nullptr)
850b57cec5SDimitry Andric     prefix = "";
860b57cec5SDimitry Andric   if (suffix == nullptr)
870b57cec5SDimitry Andric     suffix = "";
88480093f4SDimitry Andric   s << prefix << llvm::format_hex(addr, 2 + 2 * addr_size) << suffix;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric // Put an address range out to the stream with optional prefix and suffix
920b57cec5SDimitry Andric // strings.
93480093f4SDimitry Andric void lldb_private::DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr,
94480093f4SDimitry Andric                                     uint64_t hi_addr, uint32_t addr_size,
95480093f4SDimitry Andric                                     const char *prefix, const char *suffix) {
960b57cec5SDimitry Andric   if (prefix && prefix[0])
97480093f4SDimitry Andric     s << prefix;
98480093f4SDimitry Andric   DumpAddress(s, lo_addr, addr_size, "[");
99480093f4SDimitry Andric   DumpAddress(s, hi_addr, addr_size, "-", ")");
1000b57cec5SDimitry Andric   if (suffix && suffix[0])
101480093f4SDimitry Andric     s << suffix;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric size_t Stream::PutChar(char ch) { return Write(&ch, 1); }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric // Print some formatted output to the stream.
1070b57cec5SDimitry Andric size_t Stream::Printf(const char *format, ...) {
1080b57cec5SDimitry Andric   va_list args;
1090b57cec5SDimitry Andric   va_start(args, format);
1100b57cec5SDimitry Andric   size_t result = PrintfVarArg(format, args);
1110b57cec5SDimitry Andric   va_end(args);
1120b57cec5SDimitry Andric   return result;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric // Print some formatted output to the stream.
1160b57cec5SDimitry Andric size_t Stream::PrintfVarArg(const char *format, va_list args) {
1170b57cec5SDimitry Andric   llvm::SmallString<1024> buf;
1180b57cec5SDimitry Andric   VASprintf(buf, format, args);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Include the NULL termination byte for binary output
1210b57cec5SDimitry Andric   size_t length = buf.size();
1220b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
1230b57cec5SDimitry Andric     ++length;
1240b57cec5SDimitry Andric   return Write(buf.c_str(), length);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric // Print and End of Line character to the stream
1280b57cec5SDimitry Andric size_t Stream::EOL() { return PutChar('\n'); }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric size_t Stream::Indent(llvm::StringRef str) {
131*5ffd83dbSDimitry Andric   const size_t ind_length = PutCString(std::string(m_indent_level, ' '));
132*5ffd83dbSDimitry Andric   const size_t str_length = PutCString(str);
133*5ffd83dbSDimitry Andric   return ind_length + str_length;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric // Stream a character "ch" out to this stream.
1370b57cec5SDimitry Andric Stream &Stream::operator<<(char ch) {
1380b57cec5SDimitry Andric   PutChar(ch);
1390b57cec5SDimitry Andric   return *this;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric // Stream the NULL terminated C string out to this stream.
1430b57cec5SDimitry Andric Stream &Stream::operator<<(const char *s) {
1440b57cec5SDimitry Andric   Printf("%s", s);
1450b57cec5SDimitry Andric   return *this;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric Stream &Stream::operator<<(llvm::StringRef str) {
1490b57cec5SDimitry Andric   Write(str.data(), str.size());
1500b57cec5SDimitry Andric   return *this;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric // Stream the pointer value out to this stream.
1540b57cec5SDimitry Andric Stream &Stream::operator<<(const void *p) {
1550b57cec5SDimitry Andric   Printf("0x%.*tx", static_cast<int>(sizeof(const void *)) * 2, (ptrdiff_t)p);
1560b57cec5SDimitry Andric   return *this;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric // Get the current indentation level
160480093f4SDimitry Andric unsigned Stream::GetIndentLevel() const { return m_indent_level; }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric // Set the current indentation level
163480093f4SDimitry Andric void Stream::SetIndentLevel(unsigned indent_level) {
164480093f4SDimitry Andric   m_indent_level = indent_level;
165480093f4SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric // Increment the current indentation level
168480093f4SDimitry Andric void Stream::IndentMore(unsigned amount) { m_indent_level += amount; }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric // Decrement the current indentation level
171480093f4SDimitry Andric void Stream::IndentLess(unsigned amount) {
1720b57cec5SDimitry Andric   if (m_indent_level >= amount)
1730b57cec5SDimitry Andric     m_indent_level -= amount;
1740b57cec5SDimitry Andric   else
1750b57cec5SDimitry Andric     m_indent_level = 0;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric // Get the address size in bytes
1790b57cec5SDimitry Andric uint32_t Stream::GetAddressByteSize() const { return m_addr_size; }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric // Set the address size in bytes
1820b57cec5SDimitry Andric void Stream::SetAddressByteSize(uint32_t addr_size) { m_addr_size = addr_size; }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric // The flags get accessor
1850b57cec5SDimitry Andric Flags &Stream::GetFlags() { return m_flags; }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric // The flags const get accessor
1880b57cec5SDimitry Andric const Flags &Stream::GetFlags() const { return m_flags; }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric // The byte order get accessor
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric lldb::ByteOrder Stream::GetByteOrder() const { return m_byte_order; }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric size_t Stream::PrintfAsRawHex8(const char *format, ...) {
1950b57cec5SDimitry Andric   va_list args;
1960b57cec5SDimitry Andric   va_start(args, format);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   llvm::SmallString<1024> buf;
1990b57cec5SDimitry Andric   VASprintf(buf, format, args);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   ByteDelta delta(*this);
2020b57cec5SDimitry Andric   for (char C : buf)
2030b57cec5SDimitry Andric     _PutHex8(C, false);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   va_end(args);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   return *delta;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
2110b57cec5SDimitry Andric   ByteDelta delta(*this);
2120b57cec5SDimitry Andric   for (size_t i = 0; i < n; ++i)
2130b57cec5SDimitry Andric     _PutHex8(uvalue, false);
2140b57cec5SDimitry Andric   return *delta;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric void Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
2180b57cec5SDimitry Andric   if (m_flags.Test(eBinary)) {
2190b57cec5SDimitry Andric     Write(&uvalue, 1);
2200b57cec5SDimitry Andric   } else {
2210b57cec5SDimitry Andric     if (add_prefix)
2220b57cec5SDimitry Andric       PutCString("0x");
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric     static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5',
2250b57cec5SDimitry Andric                                                '6', '7', '8', '9', 'a', 'b',
2260b57cec5SDimitry Andric                                                'c', 'd', 'e', 'f'};
2270b57cec5SDimitry Andric     char nibble_chars[2];
2280b57cec5SDimitry Andric     nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
2290b57cec5SDimitry Andric     nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
2300b57cec5SDimitry Andric     Write(nibble_chars, sizeof(nibble_chars));
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric size_t Stream::PutHex8(uint8_t uvalue) {
2350b57cec5SDimitry Andric   ByteDelta delta(*this);
2360b57cec5SDimitry Andric   _PutHex8(uvalue, false);
2370b57cec5SDimitry Andric   return *delta;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) {
2410b57cec5SDimitry Andric   ByteDelta delta(*this);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
2440b57cec5SDimitry Andric     byte_order = m_byte_order;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
2470b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
2480b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2490b57cec5SDimitry Andric   } else {
2500b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
2510b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric   return *delta;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) {
2570b57cec5SDimitry Andric   ByteDelta delta(*this);
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
2600b57cec5SDimitry Andric     byte_order = m_byte_order;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
2630b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
2640b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2650b57cec5SDimitry Andric   } else {
2660b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
2670b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric   return *delta;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) {
2730b57cec5SDimitry Andric   ByteDelta delta(*this);
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
2760b57cec5SDimitry Andric     byte_order = m_byte_order;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
2790b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
2800b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2810b57cec5SDimitry Andric   } else {
2820b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
2830b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric   return *delta;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
2890b57cec5SDimitry Andric                            lldb::ByteOrder byte_order) {
2900b57cec5SDimitry Andric   switch (byte_size) {
2910b57cec5SDimitry Andric   case 1:
2920b57cec5SDimitry Andric     return PutHex8(static_cast<uint8_t>(uvalue));
2930b57cec5SDimitry Andric   case 2:
2940b57cec5SDimitry Andric     return PutHex16(static_cast<uint16_t>(uvalue), byte_order);
2950b57cec5SDimitry Andric   case 4:
2960b57cec5SDimitry Andric     return PutHex32(static_cast<uint32_t>(uvalue), byte_order);
2970b57cec5SDimitry Andric   case 8:
2980b57cec5SDimitry Andric     return PutHex64(uvalue, byte_order);
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric   return 0;
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric size_t Stream::PutPointer(void *ptr) {
3040b57cec5SDimitry Andric   return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(),
3050b57cec5SDimitry Andric                      endian::InlHostByteOrder());
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric size_t Stream::PutFloat(float f, ByteOrder byte_order) {
3090b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3100b57cec5SDimitry Andric     byte_order = m_byte_order;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order);
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric size_t Stream::PutDouble(double d, ByteOrder byte_order) {
3160b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3170b57cec5SDimitry Andric     byte_order = m_byte_order;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order);
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) {
3230b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3240b57cec5SDimitry Andric     byte_order = m_byte_order;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order);
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric size_t Stream::PutRawBytes(const void *s, size_t src_len,
3300b57cec5SDimitry Andric                            ByteOrder src_byte_order, ByteOrder dst_byte_order) {
3310b57cec5SDimitry Andric   ByteDelta delta(*this);
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   if (src_byte_order == eByteOrderInvalid)
3340b57cec5SDimitry Andric     src_byte_order = m_byte_order;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   if (dst_byte_order == eByteOrderInvalid)
3370b57cec5SDimitry Andric     dst_byte_order = m_byte_order;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   const uint8_t *src = static_cast<const uint8_t *>(s);
3400b57cec5SDimitry Andric   bool binary_was_set = m_flags.Test(eBinary);
3410b57cec5SDimitry Andric   if (!binary_was_set)
3420b57cec5SDimitry Andric     m_flags.Set(eBinary);
3430b57cec5SDimitry Andric   if (src_byte_order == dst_byte_order) {
3440b57cec5SDimitry Andric     for (size_t i = 0; i < src_len; ++i)
3450b57cec5SDimitry Andric       _PutHex8(src[i], false);
3460b57cec5SDimitry Andric   } else {
3470b57cec5SDimitry Andric     for (size_t i = src_len - 1; i < src_len; --i)
3480b57cec5SDimitry Andric       _PutHex8(src[i], false);
3490b57cec5SDimitry Andric   }
3500b57cec5SDimitry Andric   if (!binary_was_set)
3510b57cec5SDimitry Andric     m_flags.Clear(eBinary);
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   return *delta;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len,
3570b57cec5SDimitry Andric                                  ByteOrder src_byte_order,
3580b57cec5SDimitry Andric                                  ByteOrder dst_byte_order) {
3590b57cec5SDimitry Andric   ByteDelta delta(*this);
3600b57cec5SDimitry Andric   if (src_byte_order == eByteOrderInvalid)
3610b57cec5SDimitry Andric     src_byte_order = m_byte_order;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   if (dst_byte_order == eByteOrderInvalid)
3640b57cec5SDimitry Andric     dst_byte_order = m_byte_order;
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   const uint8_t *src = static_cast<const uint8_t *>(s);
3670b57cec5SDimitry Andric   bool binary_is_set = m_flags.Test(eBinary);
3680b57cec5SDimitry Andric   m_flags.Clear(eBinary);
3690b57cec5SDimitry Andric   if (src_byte_order == dst_byte_order) {
3700b57cec5SDimitry Andric     for (size_t i = 0; i < src_len; ++i)
3710b57cec5SDimitry Andric       _PutHex8(src[i], false);
3720b57cec5SDimitry Andric   } else {
3730b57cec5SDimitry Andric     for (size_t i = src_len - 1; i < src_len; --i)
3740b57cec5SDimitry Andric       _PutHex8(src[i], false);
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric   if (binary_is_set)
3770b57cec5SDimitry Andric     m_flags.Set(eBinary);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   return *delta;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric size_t Stream::PutStringAsRawHex8(llvm::StringRef s) {
3830b57cec5SDimitry Andric   ByteDelta delta(*this);
3840b57cec5SDimitry Andric   bool binary_is_set = m_flags.Test(eBinary);
3850b57cec5SDimitry Andric   m_flags.Clear(eBinary);
3860b57cec5SDimitry Andric   for (char c : s)
3870b57cec5SDimitry Andric     _PutHex8(c, false);
3880b57cec5SDimitry Andric   if (binary_is_set)
3890b57cec5SDimitry Andric     m_flags.Set(eBinary);
3900b57cec5SDimitry Andric   return *delta;
3910b57cec5SDimitry Andric }
392