blob: f50b2b30307902c010b45f89ece571a1e2138a6c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/lib/fostr/hex_dump.h"
#include <iomanip>
namespace fostr {
namespace internal {
static constexpr size_t kBytesPerLine = 16;
std::ostream& operator<<(std::ostream& os, const HexDump& value) {
const uint8_t* bytes = value.data_;
size_t bytes_remaining = value.size_;
intptr_t address = value.initial_address_;
if (bytes == nullptr) {
return os << "<null>";
}
if (address == std::numeric_limits<intptr_t>::max()) {
address = reinterpret_cast<size_t>(bytes);
}
int address_width = 4;
if (address + bytes_remaining > 0x100000000) {
address_width = 16;
} else if (address + bytes_remaining > 0x10000) {
address_width = 8;
}
if (bytes_remaining == 0) {
return os << "<zero bytes at " << std::hex << std::setw(address_width) << std::setfill('0')
<< address << std::setfill(' ') << std::dec << ">";
}
while (true) {
os << NewLine << std::hex << std::setw(address_width) << std::setfill('0') << address << " ";
std::string chars(kBytesPerLine, ' ');
for (size_t i = 0; i < kBytesPerLine; ++i) {
if (i == kBytesPerLine / 2) {
os << " ";
}
if (i >= bytes_remaining) {
os << " ";
} else {
os << " " << std::setw(2) << std::setfill('0') << static_cast<uint16_t>(*bytes);
if (*bytes >= ' ' && *bytes <= '~') {
chars[i] = *bytes;
} else {
chars[i] = '.';
}
++bytes;
}
}
os << std::setfill(' ') << " " << chars;
if (bytes_remaining <= kBytesPerLine) {
break;
}
address += kBytesPerLine;
bytes_remaining -= kBytesPerLine;
}
return os << std::dec;
}
} // namespace internal
} // namespace fostr