#pragma once
#include <util/stream/output.h>
#include <utility>
#include <util/generic/strbuf.h>
template <class T>
struct TDumper {
template <class S>
static inline void Dump(S& s, const T& t) {
s.Stream() << t;
}
};
namespace NDumpPrivate {
template <class T, class V>
inline void Dump(T& t, const V& v) {
::TDumper<V>::Dump(t, v);
}
template <class T, class V>
inline T&& operator<<(T&& t, V&& v) {
Dump(t, v);
return std::forward<T>(t);
}
struct TADLBase {
};
}
struct TDumpBase: public ::NDumpPrivate::TADLBase {
inline TDumpBase(IOutputStream& out, bool indent) noexcept
: Out(&out)
, IndentLevel(0)
, Indent(indent)
{
}
inline IOutputStream& Stream() const noexcept {
return *Out;
}
void Char(char ch);
void Char(wchar16 ch);
void String(const TStringBuf& s);
void String(const TWtringBuf& s);
void Raw(const TStringBuf& s);
IOutputStream* Out;
size_t IndentLevel;
bool Indent;
};
struct TIndentScope {
inline TIndentScope(TDumpBase& d)
: D(&d)
{
++(D->IndentLevel);
}
inline ~TIndentScope() {
--(D->IndentLevel);
}
TDumpBase* D;
};
template <class TChar>
struct TRawLiteral {
const TBasicStringBuf<TChar> S;
};
template <class TChar>
static inline TRawLiteral<TChar> DumpRaw(const TBasicStringBuf<TChar>& s) noexcept {
return {s};
}
template <class TChar>
static inline TRawLiteral<TChar> DumpRaw(const TChar* s) noexcept {
return {s};
}
template <class C>
struct TDumper<TRawLiteral<C>> {
template <class S>
static inline void Dump(S& s, const TRawLiteral<C>& v) {
s.Raw(v.S);
}
};
struct TIndentNewLine {
};
static inline TIndentNewLine IndentNewLine() noexcept {
return {};
}
template <>
struct TDumper<TIndentNewLine> {
template <class S>
static inline void Dump(S& s, const TIndentNewLine&) {
if (s.Indent) {
s << DumpRaw("\n") << DumpRaw(TString(s.IndentLevel * 4, ' ').data());
}
}
};
template <class P>
struct TDumper<const P*> {
template <class S>
static inline void Dump(S& s, const P* p) {
s.Pointer(p);
}
};
template <class P>
struct TDumper<P*>: public TDumper<const P*> {
};
struct TCharDumper {
template <class S, class V>
static inline void Dump(S& s, const V& v) {
s.Char(v);
}
};
template <class S, class V>
static inline void OutSequence(S& s, const V& v, const char* openTag, const char* closeTag) {
s.ColorScheme.Markup(s);
s << DumpRaw(openTag);
{
TIndentScope scope(s);
size_t cnt = 0;
for (const auto& x : v) {
if (cnt) {
s.ColorScheme.Markup(s);
s << DumpRaw(", ");
}
s << IndentNewLine();
s.ColorScheme.Literal(s);
s << x;
++cnt;
}
}
s << IndentNewLine();
s.ColorScheme.Markup(s);
s << DumpRaw(closeTag);
s.ColorScheme.ResetType(s);
}
struct TAssocDumper {
template <class S, class V>
static inline void Dump(S& s, const V& v) {
::OutSequence(s, v, "{", "}");
}
};
struct TSeqDumper {
template <class S, class V>
static inline void Dump(S& s, const V& v) {
::OutSequence(s, v, "[", "]");
}
};
struct TStrDumper {
template <class S, class V>
static inline void Dump(S& s, const V& v) {
s.ColorScheme.String(s);
s.String(v);
s.ColorScheme.ResetType(s);
}
};