Remote util::Printer and related cruft

pull/1955/head
Jason Rhinelander 2 years ago
parent 2f9e182b20
commit eec8244a6c
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262

@ -10,7 +10,6 @@ add_library(lokinet-util
util/logging/buffer.cpp
util/lokinet_init.c
util/mem.cpp
util/printer.cpp
util/str.cpp
util/thread/queue_manager.cpp
util/thread/threading.cpp

@ -5,7 +5,6 @@
#include "srv_data.hpp"
#include <llarp/util/buffer.hpp>
#include <llarp/util/logging.hpp>
#include <llarp/util/printer.hpp>
#include <llarp/net/ip.hpp>
#include <array>
@ -401,19 +400,18 @@ namespace llarp
}
}
std::ostream&
Message::print(std::ostream& stream, int level, int spaces) const
std::string
Message::ToString() const
{
Printer printer(stream, level, spaces);
printer.printAttributeAsHex("dns message id", hdr_id);
printer.printAttributeAsHex("fields", hdr_fields);
printer.printAttribute("questions", questions);
printer.printAttribute("answers", answers);
printer.printAttribute("nameserer", authorities);
printer.printAttribute("additional", additional);
return stream;
return fmt::format(
"[DNSMessage id={:x} fields={:x} questions={{{}}} answers={{{}}} authorities={{{}}} "
"additional={{{}}}]",
hdr_id,
hdr_fields,
fmt::format("{}", fmt::join(questions, ",")),
fmt::format("{}", fmt::join(answers, ",")),
fmt::format("{}", fmt::join(authorities, ",")),
fmt::format("{}", fmt::join(additional, ",")));
}
} // namespace dns

@ -93,16 +93,8 @@ namespace llarp
[[nodiscard]] OwnedBuffer
ToBuffer() const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
}
ToString() const;
MsgID_t hdr_id;
Fields_t hdr_fields;

@ -1,7 +1,6 @@
#include "question.hpp"
#include <llarp/util/logging.hpp>
#include <llarp/util/printer.hpp>
#include <llarp/util/str.hpp>
#include "dns.hpp"
@ -120,20 +119,7 @@ namespace llarp
std::string
Question::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
}
std::ostream&
Question::print(std::ostream& stream, int level, int spaces) const
{
std::ostringstream o;
Printer printer(o, level, spaces);
printer.printAttribute("qname", qname);
printer.printAttributeAsHex("qtype", qtype);
printer.printAttributeAsHex("qclass", qclass);
return stream;
return fmt::format("[DNSQuestion qname={} qtype={:x} qclass={:x}]", qname, qtype, qclass);
}
} // namespace dns
} // namespace llarp

@ -27,8 +27,6 @@ namespace llarp
std::string
ToString() const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
bool
operator==(const Question& other) const

@ -1,8 +1,8 @@
#include "rr.hpp"
#include "dns.hpp"
#include "util/formattable.hpp"
#include <llarp/util/mem.hpp>
#include <llarp/util/logging.hpp>
#include <llarp/util/printer.hpp>
namespace llarp
{
@ -96,25 +96,16 @@ namespace llarp
{"rdata", std::string{reinterpret_cast<const char*>(rData.data()), rData.size()}}};
}
std::ostream&
ResourceRecord::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("name", rr_name);
printer.printAttribute("type", rr_type);
printer.printAttribute("class", rr_class);
printer.printAttribute("ttl", ttl);
printer.printAttribute("rdata", rData.size());
return stream;
}
std::string
ResourceRecord::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[RR name={} type={} class={} ttl={} rdata-size={}]",
rr_name,
rr_type,
rr_class,
ttl,
rData.size());
}
bool

@ -33,8 +33,6 @@ namespace llarp
util::StatusObject
ToJSON() const override;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;

@ -7,7 +7,6 @@
#include "net.hpp"
#include <llarp/util/bencode.h>
#include <llarp/util/mem.h>
#include <llarp/util/printer.hpp>
#include <cstring>
@ -171,25 +170,12 @@ namespace llarp
port = addr.getPort();
}
std::ostream&
AddressInfo::print(std::ostream& stream, int level, int spaces) const
{
char tmp[128] = {0};
inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp));
Printer printer(stream, level, spaces);
printer.printAttribute("ip", tmp);
printer.printAttribute("port", port);
return stream;
}
std::string
AddressInfo::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
char tmp[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp));
return fmt::format("[{}]:{}", tmp, port);
}
void

@ -53,9 +53,6 @@ namespace llarp
std::variant<nuint32_t, nuint128_t>
IP() const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;
};

@ -91,9 +91,8 @@ namespace llarp
return read;
}
std::ostream&
ExitInfo::print(
std::ostream& stream, [[maybe_unused]] int level, [[maybe_unused]] int spaces) const
std::string
ExitInfo::ToString() const
{
/*
// TODO: derive these from ipAdress
@ -119,14 +118,7 @@ namespace llarp
#endif
printer.printValue(ss.str());
*/
stream << ipAddress.ToString();
return stream;
}
std::string
ExitInfo::ToString() const
{
return ipAddress.ToString();
return fmt::format("[Exit {}]", ipAddress.ToString());
}
} // namespace llarp

@ -40,9 +40,6 @@ namespace llarp
bool
DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf);
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;
};

@ -4,8 +4,6 @@
#include <algorithm>
#include <functional>
#include "../util/meta/traits.hpp"
#include <oxenc/endian.h>
namespace llarp

@ -21,24 +21,15 @@ namespace llarp
{
namespace path
{
std::ostream&
TransitHopInfo::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("tx", txID);
printer.printAttribute("rx", rxID);
printer.printAttribute("upstream", upstream);
printer.printAttribute("downstream", downstream);
return stream;
}
std::string
TransitHopInfo::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[TransitHopInfo tx={} rx={} upstream={} downstream={}]",
txID,
rxID,
upstream,
downstream);
}
TransitHop::TransitHop()
@ -440,22 +431,11 @@ namespace llarp
return SendRoutingMessage(discarded, r);
}
std::ostream&
TransitHop::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("TransitHop", info);
printer.printAttribute("started", started.count());
printer.printAttribute("lifetime", lifetime.count());
return stream;
}
std::string
TransitHop::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[TransitHop {} started={} lifetime={}", info, started.count(), lifetime.count());
}
void

@ -28,9 +28,6 @@ namespace llarp
RouterID upstream;
RouterID downstream;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;
};
@ -108,8 +105,6 @@ namespace llarp
std::string
ToString() const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
bool
Expired(llarp_time_t now) const override;

@ -53,24 +53,14 @@ namespace llarp
return true;
}
std::ostream&
PoW::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("pow timestamp", timestamp.count());
printer.printAttribute("lifetime", extendedLifetime.count());
printer.printAttribute("nonce", nonce);
return stream;
}
std::string
PoW::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[PoW timestamp={} lifetime={} nonce={}]",
timestamp.count(),
extendedLifetime.count(),
nonce);
}
} // namespace llarp

@ -38,9 +38,6 @@ namespace llarp
return !(*this == other);
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;
};

@ -7,7 +7,6 @@
#include "util/buffer.hpp"
#include "util/logging.hpp"
#include "util/mem.hpp"
#include "util/printer.hpp"
#include "util/time.hpp"
#include <oxenc/bt_serialize.h>
@ -573,27 +572,18 @@ namespace llarp
return BDecode(&buf);
}
std::ostream&
RouterContact::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("k", pubkey);
printer.printAttribute("updated", last_updated.count());
printer.printAttribute("netid", netID);
printer.printAttribute("v", version);
printer.printAttribute("ai", addrs);
printer.printAttribute("e", enckey);
printer.printAttribute("z", signature);
return stream;
}
std::string
RouterContact::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[RC k={} updated={} netid={} v={} ai={{{}}} e={} z={}]",
pubkey,
last_updated.count(),
netID,
version,
fmt::format("{}", fmt::join(addrs, ",")),
enckey,
signature);
}
} // namespace llarp

@ -192,9 +192,6 @@ namespace llarp
return last_updated < other.last_updated;
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
bool
Read(const fs::path& fname);

@ -95,24 +95,10 @@ namespace llarp
return true;
}
std::ostream&
ServiceInfo::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("e", enckey);
printer.printAttribute("s", signkey);
printer.printAttribute("v", version);
printer.printAttribute("x", vanity);
return stream;
}
std::string
ServiceInfo::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format("[ServiceInfo e={} s={} v={} x={}]", enckey, signkey, version, vanity);
}
} // namespace service

@ -63,9 +63,6 @@ namespace llarp
return Addr() < other.Addr();
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;

@ -65,26 +65,16 @@ namespace llarp
expiresAt = 0s;
}
std::ostream&
Introduction::print(std::ostream& stream, int level, int spaces) const
{
const RouterID r{router};
Printer printer(stream, level, spaces);
printer.printAttribute("k", r.ToString());
printer.printAttribute("l", latency.count());
printer.printAttribute("p", pathID);
printer.printAttribute("v", version);
printer.printAttribute("x", expiresAt.count());
return stream;
}
std::string
Introduction::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[Intro k={} l={} p={} v={} x={}]",
RouterID{router},
latency.count(),
pathID,
version,
expiresAt.count());
}
} // namespace service

@ -34,8 +34,6 @@ namespace llarp
return IsExpired(now + dlt);
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;

@ -69,24 +69,16 @@ namespace llarp::service
return signedAt < other.signedAt;
}
std::ostream&
EncryptedIntroSet::print(std::ostream& out, int levels, int spaces) const
{
Printer printer(out, levels, spaces);
printer.printAttribute("d", derivedSigningKey);
printer.printAttribute("n", nounce);
printer.printAttribute("s", signedAt.count());
printer.printAttribute("x", "[" + std::to_string(introsetPayload.size()) + " bytes]");
printer.printAttribute("z", sig);
return out;
}
std::string
EncryptedIntroSet::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[EncIntroSet d={} n={} s={} x=[{} bytes] z={}]",
derivedSigningKey,
nounce,
signedAt.count(),
introsetPayload.size(),
sig);
}
std::optional<IntroSet>
@ -427,38 +419,17 @@ namespace llarp::service
return maxTime;
}
std::ostream&
IntroSet::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("addressKeys", addressKeys);
printer.printAttribute("intros", intros);
printer.printAttribute("sntrupKey", sntrupKey);
std::string _topic = topic.ToString();
if (!_topic.empty())
{
printer.printAttribute("topic", _topic);
}
else
{
printer.printAttribute("topic", topic);
}
printer.printAttribute("signedAt", timestampSignedAt.count());
printer.printAttribute("version", version);
printer.printAttribute("sig", signature);
return stream;
}
std::string
IntroSet::ToString() const
{
std::ostringstream o;
print(o, -1, -1);
return o.str();
return fmt::format(
"[IntroSet addressKeys={} intros={{{}}} sntrupKey={} topic={} signedAt={} v={} sig={}]",
addressKeys,
fmt::format("{}", fmt::join(intros, ",")),
sntrupKey,
topic,
timestampSignedAt.count(),
version,
signature);
}
} // namespace llarp::service

@ -57,8 +57,6 @@ namespace llarp
return timestampSignedAt < other.timestampSignedAt;
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;
@ -170,8 +168,6 @@ namespace llarp
bool
Verify(llarp_time_t now) const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;
std::string
ToString() const;

@ -2,9 +2,7 @@
#include "bencode.h"
#include <llarp/util/logging.hpp>
#include <llarp/util/meta/traits.hpp>
#include <llarp/util/formattable.hpp>
#include "printer.hpp"
#include <oxenc/hex.h>
@ -283,15 +281,6 @@ namespace llarp
return true;
}
std::ostream&
print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printValue(ToHex());
return stream;
}
private:
Data m_data;
};

@ -52,7 +52,7 @@ namespace fmt
{
template <typename FormatContext>
auto
format(const fs::path& p, FormatContext& ctx)
format(const fs::path& p, FormatContext& ctx) const
{
return formatter<std::string_view>::format(p.string(), ctx);
}
@ -69,7 +69,7 @@ namespace fmt
{
template <typename FormatContext>
auto
format(const T& val, FormatContext& ctx)
format(const T& val, FormatContext& ctx) const
{
if constexpr (llarp::is_scoped_enum_v<T>)
return formatter<std::string_view>::format(ToString(val), ctx);

@ -1,209 +0,0 @@
#pragma once
#include <cstddef>
#include <type_traits>
#include <utility>
#include <tuple>
namespace llarp
{
namespace traits
{
/// Represents the empty type
struct Bottom
{};
/// Int tag
template <size_t N>
struct Tag
{
char arr[N + 1];
};
/// Type trait representing whether a type is pointer-like
template <typename T, typename _ = void>
struct is_pointy : public std::false_type
{};
// We take the following things:
// - has element_type typedef
// - has dereference operator
// - has arrow operator
template <typename T>
struct is_pointy<T, std::conditional_t<false, std::void_t<decltype(*std::declval<T>())>, void>>
: public std::true_type
{};
/// Type trait representing whether a type is an STL-style container
template <typename T, typename _ = void>
struct is_container : public std::false_type
{};
// We take that the container has begin, end and size methods to be a
// container.
// clang-format off
template < typename T >
struct is_container<
T,
std::conditional_t<
false,
std::void_t< typename T::value_type,
typename T::size_type,
typename T::iterator,
typename T::const_iterator,
decltype(std::declval<T>().size()),
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend()) >,
void > > : public std::true_type
{
};
// clang-format on
namespace Switch
{
template <size_t Selector, typename... Types>
struct Switch
{
using Type = Bottom;
};
template <typename T, typename... Types>
struct Switch<0u, T, Types...>
{
using Type = T;
};
template <size_t Selector, typename Tn, typename... Types>
struct Switch<Selector, Tn, Types...>
{
using Type = typename Switch<Selector - 1, Types...>::Type;
};
} // namespace Switch
namespace select
{
/// This provides a way to do a compile-type dispatch based on type traits
/// meta function which always returns false
template <typename>
class False : public std::false_type
{};
/// a case in the selection
template <template <typename...> class Trait = False>
class Case
{
public:
template <typename Type>
struct Selector : public Trait<Type>::type
{};
using Type = Case;
};
// clang-format off
/// implementation helper
template < typename T,
template < typename... > class Trait1,
template < typename... > class Trait2,
template < typename... > class Trait3,
template < typename... > class Trait4,
template < typename... > class Trait5,
template < typename... > class Trait6,
template < typename... > class Trait7,
template < typename... > class Trait8,
template < typename... > class Trait9 >
struct SelectHelper {
enum {
Selector = (
Trait1<T>::value ? 1 :
Trait2<T>::value ? 2 :
Trait3<T>::value ? 3 :
Trait4<T>::value ? 4 :
Trait5<T>::value ? 5 :
Trait6<T>::value ? 6 :
Trait7<T>::value ? 7 :
Trait8<T>::value ? 8 :
Trait9<T>::value ? 9 : 0
)
};
using Type = typename Switch::Switch<
Selector,
Case<>,
Case<Trait1>,
Case<Trait2>,
Case<Trait3>,
Case<Trait4>,
Case<Trait5>,
Case<Trait6>,
Case<Trait7>,
Case<Trait8>,
Case<Trait9>
>::Type;
};
template< typename Type,
template < typename... > class Trait1,
template < typename... > class Trait2 = False,
template < typename... > class Trait3 = False,
template < typename... > class Trait4 = False,
template < typename... > class Trait5 = False,
template < typename... > class Trait6 = False,
template < typename... > class Trait7 = False,
template < typename... > class Trait8 = False,
template < typename... > class Trait9 = False >
struct Select : public SelectHelper< Type,
Trait1,
Trait2,
Trait3,
Trait4,
Trait5,
Trait6,
Trait7,
Trait8,
Trait9 >::Type
{
enum {
Selector = SelectHelper< Type,
Trait1,
Trait2,
Trait3,
Trait4,
Trait5,
Trait6,
Trait7,
Trait8,
Trait9 >::Selector
};
using SelectorType = std::integral_constant<int, Selector>;
};
// clang-format on
} // namespace select
namespace detail
{
template <typename T, typename F, size_t... Is>
void
for_each(T&& t, F f, std::index_sequence<Is...>)
{
auto l = {(f(std::get<Is>(t)), 0)...};
(void)l;
}
} // namespace detail
template <typename... Ts, typename F>
void
for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, std::make_index_sequence<sizeof...(Ts)>());
}
} // namespace traits
} // namespace llarp

@ -1,197 +0,0 @@
#include "printer.hpp"
#include <cctype>
namespace llarp
{
namespace
{
static void
putSpaces(std::ostream& stream, size_t count)
{
// chunk n write
static const char spaces[] = " ";
static constexpr size_t size = sizeof(spaces) - 1;
while (size < count)
{
stream.write(spaces, size);
count -= size;
}
if (count > 0)
{
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)
{
if (!m_suppressIndent)
{
const int absSpaces = m_spaces < 0 ? -m_spaces : m_spaces;
putSpaces(m_stream, absSpaces * m_level);
}
m_stream << '[';
if (m_spaces >= 0)
{
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
Printer::printHexAddr(std::string_view name, const void* address) const
{
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
PrintHelper::printType(
std::ostream& stream,
char value,
int,
int spacesPerLevel,
traits::select::Case<std::is_fundamental>)
{
if (std::isprint(static_cast<unsigned char>(value)))
{
stream << "'" << value << "'";
}
else
{
#define PRINT_CONTROL_CHAR(x) \
case x: \
stream << #x; \
break;
switch (value)
{
PRINT_CONTROL_CHAR('\n');
PRINT_CONTROL_CHAR('\t');
PRINT_CONTROL_CHAR('\0');
default:
{
// Print as hex
FormatFlagsGuard guard(stream);
stream << std::hex << std::showbase
<< static_cast<std::uintptr_t>(static_cast<unsigned char>(value));
}
}
}
if (spacesPerLevel >= 0)
{
stream << '\n';
}
}
void
PrintHelper::printType(
std::ostream& stream,
bool value,
int,
int spacesPerLevel,
traits::select::Case<std::is_fundamental>)
{
{
FormatFlagsGuard guard(stream);
stream << std::boolalpha << value;
}
if (spacesPerLevel >= 0)
{
stream << '\n';
}
}
void
PrintHelper::printType(
std::ostream& stream,
const char* value,
int,
int spacesPerLevel,
traits::select::Case<std::is_pointer>)
{
if (value == nullptr)
{
stream << "null";
}
else
{
stream << '"' << value << '"';
}
if (spacesPerLevel >= 0)
{
stream << '\n';
}
}
void
PrintHelper::printType(
std::ostream& stream,
const void* value,
int,
int spacesPerLevel,
traits::select::Case<std::is_pointer>)
{
if (value == nullptr)
{
stream << "null";
}
else
{
FormatFlagsGuard guard(stream);
stream << std::hex << std::showbase << reinterpret_cast<std::uintptr_t>(value);
}
if (spacesPerLevel >= 0)
{
stream << '\n';
}
}
void
PrintHelper::printType(
std::ostream& stream,
const std::string_view& value,
int,
int spacesPerLevel,
traits::select::Case<traits::is_container>)
{
stream << '"' << value << '"';
if (spacesPerLevel >= 0)
{
stream << '\n';
}
}
} // namespace llarp

@ -1,583 +0,0 @@
#pragma once
#include <llarp/util/meta/traits.hpp>
#include <functional>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <string_view>
namespace llarp
{
/// simple guard class to restore stream flags.
struct FormatFlagsGuard
{
std::ios_base& m_base;
std::ios_base::fmtflags m_flags;
FormatFlagsGuard(std::ios_base& base) : m_base(base), m_flags(base.flags())
{}
~FormatFlagsGuard()
{
m_base.flags(m_flags);
}
};
/// A general-purpose, stateful printer class.
class Printer
{
private:
std::ostream& m_stream;
const int m_level;
const int m_levelPlusOne;
const bool m_suppressIndent;
const int m_spaces;
public:
template <typename Type>
using PrintFunction = std::function<std::ostream&(std::ostream&, const Type&, int, int)>;
/// Create a printer.
/// - level: the indentation level to use. If negative, suppress indentation
/// on the first line.
/// - spaces: the number of spaces to indent. If negative, put all output on
/// a single line
Printer(std::ostream& stream, int level, int spaces);
~Printer();
/// Print the given `data` to the stream, using the following strategies:
/// - If `Type` is fundamental, print to stream
/// - If `Type` is a C-style array (and not a char array), print each
/// element to the stream
/// - If `Type` is a `void *`, `const void *` or function pointer, and not
/// null, print in hex format or print "null".
/// - If `Type` is a `char *`, a `const char *`, a C-style char array, a
/// `std::string` or `std::string_view` print the string wrapped in `"`.
/// - If `Type` is a pointer type, print the pointer, followed by the value
/// if not-null.
/// - If `Type` is a pair/tuple type, print the elements of the tuple.
/// - If `Type` has STL-style iterators, print all elements in the
/// container.
/// - If `Type` is any other type, call the `print` method on that type.
template <typename Type>
void
printAttribute(std::string_view name, const Type& value) const;
template <typename Type>
void
printAttributeAsHex(std::string_view name, const Type& value) const;
template <typename InputIt>
void
printAttribute(std::string_view name, const InputIt& begin, const InputIt& end) const;
template <typename Type>
void
printValue(const Type& value) const;
template <typename InputIt>
void
printValue(const InputIt& begin, const InputIt& end) const;
template <typename Type>
void
printForeignAttribute(
std::string_view name, const Type& value, const PrintFunction<Type>& printFunction) const;
template <typename Type>
void
printForeignValue(const Type& value, const PrintFunction<Type>& printFunction) const;
void
printHexAddr(std::string_view name, const void* address) const;
void
printHexAddr(const void* address) const;
template <class Type>
void
printOrNull(std::string_view name, const Type& address) const;
template <class Type>
void
printOrNull(const Type& address) const;
private:
void
printIndent() const;
};
/// helper struct
struct PrintHelper
{
template <typename Type>
static void
print(std::ostream& stream, const Type& value, int level, int spaces);
template <typename InputIt>
static void
print(std::ostream& stream, const InputIt& begin, const InputIt& end, int level, int spaces);
// Specialisations
// Fundamental types
static void
printType(
std::ostream& stream,
char value,
int level,
int spaces,
traits::select::Case<std::is_fundamental>);
static void
printType(
std::ostream& stream,
bool value,
int level,
int spaces,
traits::select::Case<std::is_fundamental>);
template <typename Type>
static void
printType(
std::ostream& stream,
Type value,
int level,
int spaces,
traits::select::Case<std::is_fundamental>);
template <typename Type>
static void
printType(
std::ostream& stream,
Type value,
int level,
int spaces,
traits::select::Case<std::is_enum>);
// Function types
template <typename Type>
static void
printType(
std::ostream& stream,
Type value,
int level,
int spaces,
traits::select::Case<std::is_function>);
// Pointer types
static void
printType(
std::ostream& stream,
const char* value,
int level,
int spaces,
traits::select::Case<std::is_pointer>);
static void
printType(
std::ostream& stream,
const void* value,
int level,
int spaces,
traits::select::Case<std::is_pointer>);
template <typename Type>
static void
printType(
std::ostream& stream,
const Type* value,
int level,
int spaces,
traits::select::Case<std::is_pointer>);
template <typename Type>
static void
printType(
std::ostream& stream,
const Type* value,
int level,
int spaces,
traits::select::Case<std::is_array>);
// Container types
static void
printType(
std::ostream& stream,
const std::string& value,
int level,
int spaces,
traits::select::Case<traits::is_container>);
static void
printType(
std::ostream& stream,
const std::string_view& value,
int level,
int spaces,
traits::select::Case<traits::is_container>);
template <typename Type>
static void
printType(
std::ostream& stream,
const Type& value,
int level,
int spaces,
traits::select::Case<traits::is_container>);
// Utility types
template <typename Type1, typename Type2>
static void
printType(
std::ostream& stream,
const std::pair<Type1, Type2>& value,
int level,
int spaces,
traits::select::Case<>);
template <typename... Types>
static void
printType(
std::ostream& stream,
const std::tuple<Types...>& value,
int level,
int spaces,
traits::select::Case<>);
// Default type
template <typename Type>
static void
printType(
std::ostream& stream, const Type& value, int level, int spaces, traits::select::Case<>);
};
template <typename Type>
inline void
Printer::printAttribute(std::string_view name, const Type& value) const
{
assert(!name.empty());
printIndent();
m_stream << name << " = ";
PrintHelper::print(m_stream, value, -m_levelPlusOne, m_spaces);
}
template <typename Type>
inline void
Printer::printAttributeAsHex(std::string_view name, const Type& value) const
{
static_assert(std::is_integral<Type>::value, "type should be integral");
assert(!name.empty());
printIndent();
m_stream << name << " = ";
{
FormatFlagsGuard guard(m_stream);
m_stream << std::hex << value;
}
if (m_spaces >= 0)
{
m_stream << '\n';
}
}
template <typename InputIt>
inline void
Printer::printAttribute(std::string_view name, const InputIt& begin, const InputIt& end) const
{
assert(!name.empty());
printIndent();
m_stream << name << " = ";
PrintHelper::print(m_stream, begin, end, -m_levelPlusOne, m_spaces);
}
template <typename Type>
inline void
Printer::printValue(const Type& value) const
{
printIndent();
PrintHelper::print(m_stream, value, -m_levelPlusOne, m_spaces);
}
template <typename InputIt>
inline void
Printer::printValue(const InputIt& begin, const InputIt& end) const
{
printIndent();
PrintHelper::print(m_stream, begin, end, -m_levelPlusOne, m_spaces);
}
template <typename Type>
inline void
Printer::printForeignAttribute(
std::string_view name, const Type& value, const PrintFunction<Type>& printFunction) const
{
assert(!name.empty());
printIndent();
m_stream << name << " = ";
printFunction(m_stream, value, -m_levelPlusOne, m_spaces);
}
template <typename Type>
inline void
Printer::printForeignValue(const Type& value, const PrintFunction<Type>& printFunction) const
{
printIndent();
printFunction(m_stream, value, -m_levelPlusOne, m_spaces);
}
template <typename Type>
inline void
Printer::printOrNull(std::string_view name, const Type& address) const
{
assert(!name.empty());
printIndent();
m_stream << name << " = ";
if (address == nullptr)
{
m_stream << "null";
if (m_spaces >= 0)
{
m_stream << '\n';
}
}
else
{
PrintHelper::print(m_stream, *address, -m_levelPlusOne, m_spaces);
}
}
template <typename Type>
inline void
Printer::printOrNull(const Type& address) const
{
printIndent();
if (address == nullptr)
{
m_stream << "null";
if (m_spaces >= 0)
{
m_stream << '\n';
}
}
else
{
PrintHelper::print(m_stream, *address, -m_levelPlusOne, m_spaces);
}
}
template <>
inline void
Printer::printOrNull<const void*>(std::string_view name, const void* const& address) const
{
assert(!name.empty());
printIndent();
m_stream << name << " = ";
const void* temp = address;
PrintHelper::print(m_stream, temp, -m_levelPlusOne, m_spaces);
}
template <>
inline void
Printer::printOrNull<void*>(std::string_view name, void* const& address) const
{
const void* const& temp = address;
printOrNull(name, temp);
}
template <>
inline void
Printer::printOrNull<const void*>(const void* const& address) const
{
printIndent();
const void* temp = address;
PrintHelper::print(m_stream, temp, -m_levelPlusOne, m_spaces);
}
template <>
inline void
Printer::printOrNull<void*>(void* const& address) const
{
const void* const& temp = address;
printOrNull(temp);
}
// Print Helper methods
template <typename InputIt>
inline void
PrintHelper::print(
std::ostream& stream, const InputIt& begin, const InputIt& end, int level, int spaces)
{
Printer printer(stream, level, spaces);
std::for_each(begin, end, [&](const auto& x) { printer.printValue(x); });
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream, Type value, int, int spaces, traits::select::Case<std::is_fundamental>)
{
stream << value;
if (spaces >= 0)
{
stream << '\n';
}
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream, Type value, int, int spaces, traits::select::Case<std::is_enum>)
{
printType(stream, value, 0, spaces, traits::select::Case<std::is_fundamental>());
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream,
Type value,
int level,
int spaces,
traits::select::Case<std::is_function>)
{
PrintHelper::print(stream, reinterpret_cast<const void*>(value), level, spaces);
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream,
const Type* value,
int level,
int spaces,
traits::select::Case<std::is_pointer>)
{
printType(
stream,
static_cast<const void*>(value),
level,
-1,
traits::select::Case<std::is_pointer>());
if (value == nullptr)
{
if (spaces >= 0)
{
stream << '\n';
}
}
else
{
stream << ' ';
PrintHelper::print(stream, *value, level, spaces);
}
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream,
const Type* value,
int level,
int spaces,
traits::select::Case<std::is_array>)
{
printType(stream, value, level, spaces, traits::select::Case<std::is_pointer>());
}
inline void
PrintHelper::printType(
std::ostream& stream,
const std::string& value,
int level,
int spaces,
traits::select::Case<traits::is_container>)
{
printType(stream, value.c_str(), level, spaces, traits::select::Case<std::is_pointer>());
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream,
const Type& value,
int level,
int spaces,
traits::select::Case<traits::is_container>)
{
print(stream, value.begin(), value.end(), level, spaces);
}
template <typename Type1, typename Type2>
inline void
PrintHelper::printType(
std::ostream& stream,
const std::pair<Type1, Type2>& value,
int level,
int spaces,
traits::select::Case<>)
{
Printer print(stream, level, spaces);
print.printValue(value.first);
print.printValue(value.second);
}
template <typename... Types>
inline void
PrintHelper::printType(
std::ostream& stream,
const std::tuple<Types...>& value,
int level,
int spaces,
traits::select::Case<>)
{
Printer print(stream, level, spaces);
traits::for_each_in_tuple(value, [&](const auto& x) { print.printValue(x); });
}
template <typename Type>
inline void
PrintHelper::printType(
std::ostream& stream, const Type& value, int level, int spaces, traits::select::Case<>)
{
value.print(stream, level, spaces);
}
template <typename Type>
inline void
PrintHelper::print(std::ostream& stream, const Type& value, int level, int spaces)
{
using Selection = traits::select::Select<
Type,
std::is_fundamental,
std::is_enum,
std::is_function,
std::is_pointer,
std::is_array,
traits::is_container>;
PrintHelper::printType(stream, value, level, spaces, Selection());
}
} // namespace llarp

@ -37,7 +37,6 @@ add_executable(testAll
service/test_llarp_service_identity.cpp
service/test_llarp_service_name.cpp
util/meta/test_llarp_util_memfn.cpp
util/meta/test_llarp_util_traits.cpp
util/thread/test_llarp_util_queue_manager.cpp
util/thread/test_llarp_util_queue.cpp
util/test_llarp_util_aligned.cpp
@ -45,7 +44,6 @@ add_executable(testAll
util/test_llarp_util_bits.cpp
util/test_llarp_util_decaying_hashset.cpp
util/test_llarp_util_log_level.cpp
util/test_llarp_util_printer.cpp
util/test_llarp_util_str.cpp
test_llarp_encrypted_frame.cpp
test_llarp_router_contact.cpp)

@ -1,139 +0,0 @@
#include <util/meta/traits.hpp>
#include <list>
#include <catch2/catch.hpp>
using namespace llarp;
TEST_CASE("traits::Bottom smoke test")
{
traits::Bottom bottom;
(void)bottom;
SUCCEED();
}
// clang-format off
using ContainerTypes = std::tuple<
std::tuple< std::vector< int >, std::integral_constant< bool, true > >,
std::tuple< std::vector< std::string >, std::integral_constant< bool, true > >,
std::tuple< std::list< std::string >, std::integral_constant< bool, true > >,
std::tuple< std::string, std::integral_constant< bool, true > >,
std::tuple< std::shared_ptr<std::string>, std::integral_constant< bool, false > >,
std::tuple< std::tuple<std::string>, std::integral_constant< bool, false > >,
std::tuple< int, std::integral_constant< bool, false > >
>;
// clang-format on
TEMPLATE_LIST_TEST_CASE("is_container smoke test", "", ContainerTypes)
{
bool expected = std::tuple_element_t<1, TestType>::value;
bool result = traits::is_container<std::tuple_element_t<0, TestType>>::value;
REQUIRE(expected == result);
}
// clang-format off
struct A { };
struct B { };
struct C { };
struct D { };
struct E { };
struct F { };
struct G { };
struct H { };
struct I { };
struct J { };
char f(A) { return 'A'; }
char f(B) { return 'B'; }
char f(C) { return 'C'; }
char f(D) { return 'D'; }
char f(E) { return 'E'; }
char f(F) { return 'F'; }
char f(G) { return 'G'; }
char f(H) { return 'H'; }
char f(I) { return 'I'; }
char f(J) { return 'J'; }
char f(traits::Bottom) { return '0'; }
// clang-format on
// clang-format off
using namespace traits::Switch;
using SwitchTypes = std::tuple<
std::tuple<std::integral_constant<char, 'A'>, Switch< 0, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'B'>, Switch< 1, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'C'>, Switch< 2, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'D'>, Switch< 3, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'E'>, Switch< 4, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'F'>, Switch< 5, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'G'>, Switch< 6, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'H'>, Switch< 7, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'I'>, Switch< 8, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'J'>, Switch< 9, A, B, C, D, E, F, G, H, I, J > >,
std::tuple<std::integral_constant<char, 'J'>, Switch< 9, C, C, C, C, C, C, C, C, C, J > >,
std::tuple<std::integral_constant<char, 'C'>, Switch< 6, C, C, C, C, C, C, C, C, C, J > >,
std::tuple<std::integral_constant<char, '0'>, Switch< 10, A, B, C, D, E, F, G, H, I, J > >
>;
// clang-format off
TEMPLATE_LIST_TEST_CASE("Switch smoke test", "", SwitchTypes)
{
char expected = std::tuple_element_t<0, TestType>::value;
using InputType = typename std::tuple_element_t<1, TestType>::Type;
char result = f(InputType());
REQUIRE(expected == result);
}
template<typename T>
using is_bool = std::is_same<T, bool>;
template<typename T>
using is_char = std::is_same<T, char>;
template<typename T>
using is_string = std::is_same<T, std::string>;
char dispatch(traits::select::Case<>) { return '0'; }
char dispatch(traits::select::Case<is_bool>) { return 'b'; }
char dispatch(traits::select::Case<is_char>) { return 'c'; }
char dispatch(traits::select::Case<is_string>) { return 's'; }
template < typename Type >
char
selectCase()
{
using Selection = traits::select::Select<Type, is_bool, is_char, is_string >;
return dispatch(Selection());
}
// clang-format off
using SelectTypes = std::tuple<
std::tuple<std::integral_constant<char, '0'>, double >,
std::tuple<std::integral_constant<char, 'b'>, bool >,
std::tuple<std::integral_constant<char, 'c'>, char >,
std::tuple<std::integral_constant<char, 's'>, std::string >
>;
// clang-format on
TEMPLATE_LIST_TEST_CASE("selectCase smoke test", "", SelectTypes)
{
char expected = std::tuple_element_t<0, TestType>::value;
char result = selectCase<std::tuple_element_t<1, TestType>>();
REQUIRE(expected == result);
}
// clang-format on
// clang-format off
using PointerTypes = std::tuple<
std::tuple< int *, std::true_type >,
std::tuple< int, std::integral_constant< bool, false > >,
std::tuple< std::shared_ptr<int>, std::true_type >,
std::tuple< std::unique_ptr<int>, std::true_type >
>;
// clang-format on
TEMPLATE_LIST_TEST_CASE("is_pointy smoke test", "", PointerTypes)
{
bool expected = std::tuple_element_t<1, TestType>::value;
bool result = traits::is_pointy<std::tuple_element_t<0, TestType>>::value;
REQUIRE(expected == result);
}

@ -1,94 +0,0 @@
#include <util/printer.hpp>
#include <catch2/catch.hpp>
#include <sstream>
#include <map>
using namespace llarp;
struct PrintableType
{
std::ostream &
print(std::ostream &stream, int level, int spaces) const
{
stream << "PrintableType " << level << " " << spaces;
return stream;
}
};
template <typename T>
std::string print(const T &x) {
std::ostringstream os;
{
Printer printer(os, -1, -1);
printer.printValue(x);
}
return os.str();
}
TEST_CASE("printable types", "[printer]") {
REQUIRE( print(char('a')) == "[ 'a' ]" );
REQUIRE( print(bool(true)) == "[ true ]" );
REQUIRE( print(bool(false)) == "[ false ]" );
REQUIRE( print(short(123)) == "[ 123 ]" );
REQUIRE( print(int(std::numeric_limits<int>::max() - 1)) == "[ 2147483646 ]" );
REQUIRE( print(static_cast< unsigned int >(std::numeric_limits< int >::max()) + 1) == "[ 2147483648 ]" );
using Catch::Matchers::StartsWith;
using Catch::Matchers::EndsWith;
static const char PTR_TYPE[] = "abacus";
REQUIRE_THAT( print(static_cast< const void * >(PTR_TYPE)), StartsWith("[ 0x") && EndsWith(" ]") );
REQUIRE( print(static_cast< const char * >(PTR_TYPE)) == R"([ "abacus" ])" );
REQUIRE( print(std::string("abacus")) == R"([ "abacus" ])" );
static const int INT_VAL = 100;
REQUIRE_THAT( print(static_cast< const int * >(&INT_VAL)), StartsWith("[ 0x") && EndsWith(" ]") );
REQUIRE( print(std::pair< int, std::string >(100, "abacus")) == R"([ [ 100 "abacus" ] ])" );
REQUIRE( print(std::tuple< int, std::string, int >(100, "abacus", 123)) == R"([ [ 100 "abacus" 123 ] ])" );
REQUIRE( print(std::map< std::string, char >{{"one", 'a'}, {"two", 'b'}, {"three", 'c'}})
== R"([ [ [ "one" 'a' ] [ "three" 'c' ] [ "two" 'b' ] ] ])" );
REQUIRE( print(PrintableType()) == "[ PrintableType -2 -1 ]" );
};
template <typename T>
std::string printAttribute(const std::string& attr, const T &x) {
std::ostringstream os;
{
Printer printer(os, -1, -1);
printer.printAttribute(attr, x);
}
return os.str();
}
TEST_CASE("printable types, with attribute", "[printer]") {
REQUIRE( printAttribute("fee", char('a')) == "[ fee = 'a' ]" );
REQUIRE( printAttribute("fi", int(32)) == "[ fi = 32 ]" );
REQUIRE( printAttribute("fo", std::map< std::string, char >{{"one", 'a'}, {"two", 'b'}, {"three", 'c'}})
== R"([ fo = [ [ "one" 'a' ] [ "three" 'c' ] [ "two" 'b' ] ] ])" );
REQUIRE( printAttribute("fum", PrintableType()) == "[ fum = PrintableType -2 -1 ]");
}
void printAnother(Printer &) {}
template <typename T, typename... Tmore>
void printAnother(Printer &p, const std::string &attr, const T& x, const Tmore&... more) {
p.printAttribute(attr, x);
printAnother(p, more...);
}
template <typename... T>
std::string printMany(const T&... x) {
std::ostringstream os;
{
Printer p(os, -1, -1);
printAnother(p, x...);
}
return os.str();
}
TEST_CASE("printable types, with multiple attributes", "[printer]") {
REQUIRE( printMany("val", 1, "v2", 2, "v3", 3, "str", std::string{"xxx"})
== "[ val = 1 v2 = 2 v3 = 3 str = \"xxx\" ]" );
REQUIRE( printMany("str", std::string{"xxx"}) == "[ str = \"xxx\" ]" );
}
Loading…
Cancel
Save