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