15ffd83dbSDimitry 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 
115f757f3fSDimitry Andric #include "lldb/Utility/AnsiTerminal.h"
120b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
130b57cec5SDimitry Andric #include "lldb/Utility/VASPrintf.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
15480093f4SDimitry Andric #include "llvm/Support/Format.h"
160b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
175f757f3fSDimitry Andric #include "llvm/Support/Regex.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include <string>
200b57cec5SDimitry Andric 
21fe6060f1SDimitry Andric #include <cinttypes>
22fe6060f1SDimitry Andric #include <cstddef>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace lldb;
250b57cec5SDimitry Andric using namespace lldb_private;
260b57cec5SDimitry Andric 
Stream(uint32_t flags,uint32_t addr_size,ByteOrder byte_order,bool colors)275ffd83dbSDimitry Andric Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order,
285ffd83dbSDimitry Andric                bool colors)
290b57cec5SDimitry Andric     : m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order),
3081ad6265SDimitry Andric       m_forwarder(*this, colors) {}
310b57cec5SDimitry Andric 
Stream(bool colors)325ffd83dbSDimitry Andric Stream::Stream(bool colors)
33fe6060f1SDimitry Andric     : m_flags(0), m_byte_order(endian::InlHostByteOrder()),
34fe6060f1SDimitry Andric       m_forwarder(*this, colors) {}
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric // Destructor
37fe6060f1SDimitry Andric Stream::~Stream() = default;
380b57cec5SDimitry Andric 
SetByteOrder(ByteOrder byte_order)390b57cec5SDimitry Andric ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
400b57cec5SDimitry Andric   ByteOrder old_byte_order = m_byte_order;
410b57cec5SDimitry Andric   m_byte_order = byte_order;
420b57cec5SDimitry Andric   return old_byte_order;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Put an offset "uval" out to the stream using the printf format in "format".
Offset(uint32_t uval,const char * format)460b57cec5SDimitry Andric void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric // Put an SLEB128 "uval" out to the stream using the printf format in "format".
PutSLEB128(int64_t sval)490b57cec5SDimitry Andric size_t Stream::PutSLEB128(int64_t sval) {
500b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
510b57cec5SDimitry Andric     return llvm::encodeSLEB128(sval, m_forwarder);
520b57cec5SDimitry Andric   else
530b57cec5SDimitry Andric     return Printf("0x%" PRIi64, sval);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // Put an ULEB128 "uval" out to the stream using the printf format in "format".
PutULEB128(uint64_t uval)570b57cec5SDimitry Andric size_t Stream::PutULEB128(uint64_t uval) {
580b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
590b57cec5SDimitry Andric     return llvm::encodeULEB128(uval, m_forwarder);
600b57cec5SDimitry Andric   else
610b57cec5SDimitry Andric     return Printf("0x%" PRIx64, uval);
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric // Print a raw NULL terminated C string to the stream.
PutCString(llvm::StringRef str)650b57cec5SDimitry Andric size_t Stream::PutCString(llvm::StringRef str) {
660b57cec5SDimitry Andric   size_t bytes_written = 0;
670b57cec5SDimitry Andric   bytes_written = Write(str.data(), str.size());
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   // when in binary mode, emit the NULL terminator
700b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
710b57cec5SDimitry Andric     bytes_written += PutChar('\0');
720b57cec5SDimitry Andric   return bytes_written;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
PutCStringColorHighlighted(llvm::StringRef text,std::optional<HighlightSettings> pattern_info)757a6dacacSDimitry Andric void Stream::PutCStringColorHighlighted(
767a6dacacSDimitry Andric     llvm::StringRef text, std::optional<HighlightSettings> pattern_info) {
777a6dacacSDimitry Andric   // Only apply color formatting when a pattern information is specified.
787a6dacacSDimitry Andric   // Otherwise, output the text without color formatting.
797a6dacacSDimitry Andric   if (!pattern_info.has_value()) {
805f757f3fSDimitry Andric     PutCString(text);
815f757f3fSDimitry Andric     return;
825f757f3fSDimitry Andric   }
835f757f3fSDimitry Andric 
847a6dacacSDimitry Andric   llvm::Regex reg_pattern(pattern_info->pattern);
855f757f3fSDimitry Andric   llvm::SmallVector<llvm::StringRef, 1> matches;
865f757f3fSDimitry Andric   llvm::StringRef remaining = text;
875f757f3fSDimitry Andric   std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
887a6dacacSDimitry Andric       pattern_info->prefix.str() + "%.*s" + pattern_info->suffix.str());
895f757f3fSDimitry Andric   while (reg_pattern.match(remaining, &matches)) {
905f757f3fSDimitry Andric     llvm::StringRef match = matches[0];
915f757f3fSDimitry Andric     size_t match_start_pos = match.data() - remaining.data();
925f757f3fSDimitry Andric     PutCString(remaining.take_front(match_start_pos));
935f757f3fSDimitry Andric     Printf(format_str.c_str(), match.size(), match.data());
945f757f3fSDimitry Andric     remaining = remaining.drop_front(match_start_pos + match.size());
955f757f3fSDimitry Andric   }
965f757f3fSDimitry Andric   if (remaining.size())
975f757f3fSDimitry Andric     PutCString(remaining);
985f757f3fSDimitry Andric }
995f757f3fSDimitry Andric 
1000b57cec5SDimitry Andric // Print a double quoted NULL terminated C string to the stream using the
1010b57cec5SDimitry Andric // printf format in "format".
QuotedCString(const char * cstr,const char * format)1020b57cec5SDimitry Andric void Stream::QuotedCString(const char *cstr, const char *format) {
1030b57cec5SDimitry Andric   Printf(format, cstr);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric // Put an address "addr" out to the stream with optional prefix and suffix
1070b57cec5SDimitry Andric // strings.
DumpAddress(llvm::raw_ostream & s,uint64_t addr,uint32_t addr_size,const char * prefix,const char * suffix)108480093f4SDimitry Andric void lldb_private::DumpAddress(llvm::raw_ostream &s, uint64_t addr,
109480093f4SDimitry Andric                                uint32_t addr_size, const char *prefix,
1100b57cec5SDimitry Andric                                const char *suffix) {
1110b57cec5SDimitry Andric   if (prefix == nullptr)
1120b57cec5SDimitry Andric     prefix = "";
1130b57cec5SDimitry Andric   if (suffix == nullptr)
1140b57cec5SDimitry Andric     suffix = "";
115480093f4SDimitry Andric   s << prefix << llvm::format_hex(addr, 2 + 2 * addr_size) << suffix;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric // Put an address range out to the stream with optional prefix and suffix
1190b57cec5SDimitry Andric // strings.
DumpAddressRange(llvm::raw_ostream & s,uint64_t lo_addr,uint64_t hi_addr,uint32_t addr_size,const char * prefix,const char * suffix)120480093f4SDimitry Andric void lldb_private::DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr,
121480093f4SDimitry Andric                                     uint64_t hi_addr, uint32_t addr_size,
122480093f4SDimitry Andric                                     const char *prefix, const char *suffix) {
1230b57cec5SDimitry Andric   if (prefix && prefix[0])
124480093f4SDimitry Andric     s << prefix;
125480093f4SDimitry Andric   DumpAddress(s, lo_addr, addr_size, "[");
126480093f4SDimitry Andric   DumpAddress(s, hi_addr, addr_size, "-", ")");
1270b57cec5SDimitry Andric   if (suffix && suffix[0])
128480093f4SDimitry Andric     s << suffix;
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
PutChar(char ch)1310b57cec5SDimitry Andric size_t Stream::PutChar(char ch) { return Write(&ch, 1); }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric // Print some formatted output to the stream.
Printf(const char * format,...)1340b57cec5SDimitry Andric size_t Stream::Printf(const char *format, ...) {
1350b57cec5SDimitry Andric   va_list args;
1360b57cec5SDimitry Andric   va_start(args, format);
1370b57cec5SDimitry Andric   size_t result = PrintfVarArg(format, args);
1380b57cec5SDimitry Andric   va_end(args);
1390b57cec5SDimitry Andric   return result;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric // Print some formatted output to the stream.
PrintfVarArg(const char * format,va_list args)1430b57cec5SDimitry Andric size_t Stream::PrintfVarArg(const char *format, va_list args) {
1440b57cec5SDimitry Andric   llvm::SmallString<1024> buf;
1450b57cec5SDimitry Andric   VASprintf(buf, format, args);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   // Include the NULL termination byte for binary output
1480b57cec5SDimitry Andric   size_t length = buf.size();
1490b57cec5SDimitry Andric   if (m_flags.Test(eBinary))
1500b57cec5SDimitry Andric     ++length;
1510b57cec5SDimitry Andric   return Write(buf.c_str(), length);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric // Print and End of Line character to the stream
EOL()1550b57cec5SDimitry Andric size_t Stream::EOL() { return PutChar('\n'); }
1560b57cec5SDimitry Andric 
Indent(llvm::StringRef str)1570b57cec5SDimitry Andric size_t Stream::Indent(llvm::StringRef str) {
1585ffd83dbSDimitry Andric   const size_t ind_length = PutCString(std::string(m_indent_level, ' '));
1595ffd83dbSDimitry Andric   const size_t str_length = PutCString(str);
1605ffd83dbSDimitry Andric   return ind_length + str_length;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric // Stream a character "ch" out to this stream.
operator <<(char ch)1640b57cec5SDimitry Andric Stream &Stream::operator<<(char ch) {
1650b57cec5SDimitry Andric   PutChar(ch);
1660b57cec5SDimitry Andric   return *this;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric // Stream the NULL terminated C string out to this stream.
operator <<(const char * s)1700b57cec5SDimitry Andric Stream &Stream::operator<<(const char *s) {
1710b57cec5SDimitry Andric   Printf("%s", s);
1720b57cec5SDimitry Andric   return *this;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
operator <<(llvm::StringRef str)1750b57cec5SDimitry Andric Stream &Stream::operator<<(llvm::StringRef str) {
1760b57cec5SDimitry Andric   Write(str.data(), str.size());
1770b57cec5SDimitry Andric   return *this;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric // Stream the pointer value out to this stream.
operator <<(const void * p)1810b57cec5SDimitry Andric Stream &Stream::operator<<(const void *p) {
1820b57cec5SDimitry Andric   Printf("0x%.*tx", static_cast<int>(sizeof(const void *)) * 2, (ptrdiff_t)p);
1830b57cec5SDimitry Andric   return *this;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric // Get the current indentation level
GetIndentLevel() const187480093f4SDimitry Andric unsigned Stream::GetIndentLevel() const { return m_indent_level; }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric // Set the current indentation level
SetIndentLevel(unsigned indent_level)190480093f4SDimitry Andric void Stream::SetIndentLevel(unsigned indent_level) {
191480093f4SDimitry Andric   m_indent_level = indent_level;
192480093f4SDimitry Andric }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric // Increment the current indentation level
IndentMore(unsigned amount)195480093f4SDimitry Andric void Stream::IndentMore(unsigned amount) { m_indent_level += amount; }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric // Decrement the current indentation level
IndentLess(unsigned amount)198480093f4SDimitry Andric void Stream::IndentLess(unsigned amount) {
1990b57cec5SDimitry Andric   if (m_indent_level >= amount)
2000b57cec5SDimitry Andric     m_indent_level -= amount;
2010b57cec5SDimitry Andric   else
2020b57cec5SDimitry Andric     m_indent_level = 0;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric // Get the address size in bytes
GetAddressByteSize() const2060b57cec5SDimitry Andric uint32_t Stream::GetAddressByteSize() const { return m_addr_size; }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric // Set the address size in bytes
SetAddressByteSize(uint32_t addr_size)2090b57cec5SDimitry Andric void Stream::SetAddressByteSize(uint32_t addr_size) { m_addr_size = addr_size; }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric // The flags get accessor
GetFlags()2120b57cec5SDimitry Andric Flags &Stream::GetFlags() { return m_flags; }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric // The flags const get accessor
GetFlags() const2150b57cec5SDimitry Andric const Flags &Stream::GetFlags() const { return m_flags; }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric // The byte order get accessor
2180b57cec5SDimitry Andric 
GetByteOrder() const2190b57cec5SDimitry Andric lldb::ByteOrder Stream::GetByteOrder() const { return m_byte_order; }
2200b57cec5SDimitry Andric 
PrintfAsRawHex8(const char * format,...)2210b57cec5SDimitry Andric size_t Stream::PrintfAsRawHex8(const char *format, ...) {
2220b57cec5SDimitry Andric   va_list args;
2230b57cec5SDimitry Andric   va_start(args, format);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   llvm::SmallString<1024> buf;
2260b57cec5SDimitry Andric   VASprintf(buf, format, args);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   ByteDelta delta(*this);
2290b57cec5SDimitry Andric   for (char C : buf)
2300b57cec5SDimitry Andric     _PutHex8(C, false);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   va_end(args);
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   return *delta;
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
PutNHex8(size_t n,uint8_t uvalue)2370b57cec5SDimitry Andric size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
2380b57cec5SDimitry Andric   ByteDelta delta(*this);
2390b57cec5SDimitry Andric   for (size_t i = 0; i < n; ++i)
2400b57cec5SDimitry Andric     _PutHex8(uvalue, false);
2410b57cec5SDimitry Andric   return *delta;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
_PutHex8(uint8_t uvalue,bool add_prefix)2440b57cec5SDimitry Andric void Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
2450b57cec5SDimitry Andric   if (m_flags.Test(eBinary)) {
2460b57cec5SDimitry Andric     Write(&uvalue, 1);
2470b57cec5SDimitry Andric   } else {
2480b57cec5SDimitry Andric     if (add_prefix)
2490b57cec5SDimitry Andric       PutCString("0x");
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5',
2520b57cec5SDimitry Andric                                                '6', '7', '8', '9', 'a', 'b',
2530b57cec5SDimitry Andric                                                'c', 'd', 'e', 'f'};
2540b57cec5SDimitry Andric     char nibble_chars[2];
2550b57cec5SDimitry Andric     nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
2560b57cec5SDimitry Andric     nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
2570b57cec5SDimitry Andric     Write(nibble_chars, sizeof(nibble_chars));
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
PutHex8(uint8_t uvalue)2610b57cec5SDimitry Andric size_t Stream::PutHex8(uint8_t uvalue) {
2620b57cec5SDimitry Andric   ByteDelta delta(*this);
2630b57cec5SDimitry Andric   _PutHex8(uvalue, false);
2640b57cec5SDimitry Andric   return *delta;
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
PutHex16(uint16_t uvalue,ByteOrder byte_order)2670b57cec5SDimitry Andric size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) {
2680b57cec5SDimitry Andric   ByteDelta delta(*this);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
2710b57cec5SDimitry Andric     byte_order = m_byte_order;
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
2740b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
2750b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2760b57cec5SDimitry Andric   } else {
2770b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
2780b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric   return *delta;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
PutHex32(uint32_t uvalue,ByteOrder byte_order)2830b57cec5SDimitry Andric size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) {
2840b57cec5SDimitry Andric   ByteDelta delta(*this);
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
2870b57cec5SDimitry Andric     byte_order = m_byte_order;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
2900b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
2910b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2920b57cec5SDimitry Andric   } else {
2930b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
2940b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
2950b57cec5SDimitry Andric   }
2960b57cec5SDimitry Andric   return *delta;
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
PutHex64(uint64_t uvalue,ByteOrder byte_order)2990b57cec5SDimitry Andric size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) {
3000b57cec5SDimitry Andric   ByteDelta delta(*this);
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3030b57cec5SDimitry Andric     byte_order = m_byte_order;
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   if (byte_order == eByteOrderLittle) {
3060b57cec5SDimitry Andric     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
3070b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
3080b57cec5SDimitry Andric   } else {
3090b57cec5SDimitry Andric     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
3100b57cec5SDimitry Andric       _PutHex8(static_cast<uint8_t>(uvalue >> (byte * 8)), false);
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric   return *delta;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
PutMaxHex64(uint64_t uvalue,size_t byte_size,lldb::ByteOrder byte_order)3150b57cec5SDimitry Andric size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
3160b57cec5SDimitry Andric                            lldb::ByteOrder byte_order) {
3170b57cec5SDimitry Andric   switch (byte_size) {
3180b57cec5SDimitry Andric   case 1:
3190b57cec5SDimitry Andric     return PutHex8(static_cast<uint8_t>(uvalue));
3200b57cec5SDimitry Andric   case 2:
3210b57cec5SDimitry Andric     return PutHex16(static_cast<uint16_t>(uvalue), byte_order);
3220b57cec5SDimitry Andric   case 4:
3230b57cec5SDimitry Andric     return PutHex32(static_cast<uint32_t>(uvalue), byte_order);
3240b57cec5SDimitry Andric   case 8:
3250b57cec5SDimitry Andric     return PutHex64(uvalue, byte_order);
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric   return 0;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
PutPointer(void * ptr)3300b57cec5SDimitry Andric size_t Stream::PutPointer(void *ptr) {
3310b57cec5SDimitry Andric   return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(),
3320b57cec5SDimitry Andric                      endian::InlHostByteOrder());
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
PutFloat(float f,ByteOrder byte_order)3350b57cec5SDimitry Andric size_t Stream::PutFloat(float f, ByteOrder byte_order) {
3360b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3370b57cec5SDimitry Andric     byte_order = m_byte_order;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order);
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
PutDouble(double d,ByteOrder byte_order)3420b57cec5SDimitry Andric size_t Stream::PutDouble(double d, ByteOrder byte_order) {
3430b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3440b57cec5SDimitry Andric     byte_order = m_byte_order;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order);
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
PutLongDouble(long double ld,ByteOrder byte_order)3490b57cec5SDimitry Andric size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) {
3500b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid)
3510b57cec5SDimitry Andric     byte_order = m_byte_order;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order);
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
PutRawBytes(const void * s,size_t src_len,ByteOrder src_byte_order,ByteOrder dst_byte_order)3560b57cec5SDimitry Andric size_t Stream::PutRawBytes(const void *s, size_t src_len,
3570b57cec5SDimitry Andric                            ByteOrder src_byte_order, ByteOrder dst_byte_order) {
3580b57cec5SDimitry Andric   ByteDelta delta(*this);
3590b57cec5SDimitry Andric 
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_was_set = m_flags.Test(eBinary);
3680b57cec5SDimitry Andric   if (!binary_was_set)
3690b57cec5SDimitry Andric     m_flags.Set(eBinary);
3700b57cec5SDimitry Andric   if (src_byte_order == dst_byte_order) {
3710b57cec5SDimitry Andric     for (size_t i = 0; i < src_len; ++i)
3720b57cec5SDimitry Andric       _PutHex8(src[i], false);
3730b57cec5SDimitry Andric   } else {
37481ad6265SDimitry Andric     for (size_t i = src_len; i > 0; --i)
37581ad6265SDimitry Andric       _PutHex8(src[i - 1], false);
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric   if (!binary_was_set)
3780b57cec5SDimitry Andric     m_flags.Clear(eBinary);
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   return *delta;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
PutBytesAsRawHex8(const void * s,size_t src_len,ByteOrder src_byte_order,ByteOrder dst_byte_order)3830b57cec5SDimitry Andric size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len,
3840b57cec5SDimitry Andric                                  ByteOrder src_byte_order,
3850b57cec5SDimitry Andric                                  ByteOrder dst_byte_order) {
3860b57cec5SDimitry Andric   ByteDelta delta(*this);
38781ad6265SDimitry Andric 
3880b57cec5SDimitry Andric   if (src_byte_order == eByteOrderInvalid)
3890b57cec5SDimitry Andric     src_byte_order = m_byte_order;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   if (dst_byte_order == eByteOrderInvalid)
3920b57cec5SDimitry Andric     dst_byte_order = m_byte_order;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   const uint8_t *src = static_cast<const uint8_t *>(s);
3950b57cec5SDimitry Andric   bool binary_is_set = m_flags.Test(eBinary);
3960b57cec5SDimitry Andric   m_flags.Clear(eBinary);
3970b57cec5SDimitry Andric   if (src_byte_order == dst_byte_order) {
3980b57cec5SDimitry Andric     for (size_t i = 0; i < src_len; ++i)
3990b57cec5SDimitry Andric       _PutHex8(src[i], false);
4000b57cec5SDimitry Andric   } else {
40181ad6265SDimitry Andric     for (size_t i = src_len; i > 0; --i)
40281ad6265SDimitry Andric       _PutHex8(src[i - 1], false);
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   if (binary_is_set)
4050b57cec5SDimitry Andric     m_flags.Set(eBinary);
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   return *delta;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
PutStringAsRawHex8(llvm::StringRef s)4100b57cec5SDimitry Andric size_t Stream::PutStringAsRawHex8(llvm::StringRef s) {
4110b57cec5SDimitry Andric   ByteDelta delta(*this);
4120b57cec5SDimitry Andric   bool binary_is_set = m_flags.Test(eBinary);
4130b57cec5SDimitry Andric   m_flags.Clear(eBinary);
4140b57cec5SDimitry Andric   for (char c : s)
4150b57cec5SDimitry Andric     _PutHex8(c, false);
4160b57cec5SDimitry Andric   if (binary_is_set)
4170b57cec5SDimitry Andric     m_flags.Set(eBinary);
4180b57cec5SDimitry Andric   return *delta;
4190b57cec5SDimitry Andric }
420