2019-02-24 20:50:49 +00:00
|
|
|
#include <util/printer.hpp>
|
|
|
|
|
2019-07-16 23:52:05 +00:00
|
|
|
#include <cctype>
|
|
|
|
|
2019-02-24 20:50:49 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
static void
|
|
|
|
putSpaces(std::ostream& stream, size_t count)
|
|
|
|
{
|
|
|
|
// chunk n write
|
2020-04-07 18:38:56 +00:00
|
|
|
static const char spaces[] = " ";
|
2019-02-24 20:50:49 +00:00
|
|
|
static constexpr size_t size = sizeof(spaces) - 1;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
while (size < count)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream.write(spaces, size);
|
|
|
|
count -= size;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (count > 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream.write(spaces, count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
Printer::Printer(std::ostream& stream, int level, int spacesPerLevel)
|
|
|
|
: m_stream(stream)
|
|
|
|
, m_level(level < 0 ? -level : level)
|
|
|
|
, m_levelPlusOne(m_level + 1)
|
|
|
|
, m_suppressIndent(level < 0)
|
|
|
|
, m_spaces(spacesPerLevel)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!m_suppressIndent)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
const int absSpaces = m_spaces < 0 ? -m_spaces : m_spaces;
|
|
|
|
putSpaces(m_stream, absSpaces * m_level);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_stream << '[';
|
2020-04-07 18:38:56 +00:00
|
|
|
if (m_spaces >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
m_stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Printer::~Printer()
|
|
|
|
{
|
|
|
|
putSpaces(m_stream, m_spaces < 0 ? 1 : m_spaces * m_level);
|
|
|
|
m_stream << ']';
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Printer::printIndent() const
|
|
|
|
{
|
|
|
|
putSpaces(m_stream, m_spaces < 0 ? 1 : m_spaces * m_levelPlusOne);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-01 19:51:15 +00:00
|
|
|
Printer::printHexAddr(std::string_view name, const void* address) const
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
printIndent();
|
|
|
|
m_stream << name << " = ";
|
|
|
|
|
|
|
|
PrintHelper::print(m_stream, address, -m_levelPlusOne, m_spaces);
|
|
|
|
}
|
|
|
|
void
|
|
|
|
Printer::printHexAddr(const void* address) const
|
|
|
|
{
|
|
|
|
printIndent();
|
|
|
|
PrintHelper::print(m_stream, address, -m_levelPlusOne, m_spaces);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PrintHelper::printType(
|
|
|
|
std::ostream& stream,
|
|
|
|
char value,
|
|
|
|
int,
|
|
|
|
int spacesPerLevel,
|
|
|
|
traits::select::Case<std::is_fundamental>)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (std::isprint(static_cast<unsigned char>(value)))
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << "'" << value << "'";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#define PRINT_CONTROL_CHAR(x) \
|
|
|
|
case x: \
|
|
|
|
stream << #x; \
|
|
|
|
break;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
switch (value)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
PRINT_CONTROL_CHAR('\n');
|
|
|
|
PRINT_CONTROL_CHAR('\t');
|
|
|
|
PRINT_CONTROL_CHAR('\0');
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
// Print as hex
|
|
|
|
FormatFlagsGuard guard(stream);
|
|
|
|
stream << std::hex << std::showbase
|
2020-04-07 18:38:56 +00:00
|
|
|
<< static_cast<std::uintptr_t>(static_cast<unsigned char>(value));
|
2019-02-24 20:50:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (spacesPerLevel >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PrintHelper::printType(
|
|
|
|
std::ostream& stream,
|
|
|
|
bool value,
|
|
|
|
int,
|
|
|
|
int spacesPerLevel,
|
|
|
|
traits::select::Case<std::is_fundamental>)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
{
|
|
|
|
FormatFlagsGuard guard(stream);
|
|
|
|
stream << std::boolalpha << value;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (spacesPerLevel >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PrintHelper::printType(
|
|
|
|
std::ostream& stream,
|
|
|
|
const char* value,
|
|
|
|
int,
|
|
|
|
int spacesPerLevel,
|
|
|
|
traits::select::Case<std::is_pointer>)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (value == nullptr)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << "null";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stream << '"' << value << '"';
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (spacesPerLevel >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PrintHelper::printType(
|
|
|
|
std::ostream& stream,
|
|
|
|
const void* value,
|
|
|
|
int,
|
|
|
|
int spacesPerLevel,
|
|
|
|
traits::select::Case<std::is_pointer>)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (value == nullptr)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << "null";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FormatFlagsGuard guard(stream);
|
2020-04-07 18:38:56 +00:00
|
|
|
stream << std::hex << std::showbase << reinterpret_cast<std::uintptr_t>(value);
|
2019-02-24 20:50:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (spacesPerLevel >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PrintHelper::printType(
|
|
|
|
std::ostream& stream,
|
2020-05-01 19:51:15 +00:00
|
|
|
const std::string_view& value,
|
2020-04-07 18:38:56 +00:00
|
|
|
int,
|
|
|
|
int spacesPerLevel,
|
|
|
|
traits::select::Case<traits::is_container>)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '"' << value << '"';
|
2020-04-07 18:38:56 +00:00
|
|
|
if (spacesPerLevel >= 0)
|
2019-02-24 20:50:49 +00:00
|
|
|
{
|
|
|
|
stream << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace llarp
|