ZeroErr
Loading...
Searching...
No Matches
print.h
Go to the documentation of this file.
1#pragma once
3
4#include "zeroerr/color.h"
6
7
8#ifdef __GNUG__
9#include <cxxabi.h>
10#endif
11
12#if defined(ZEROERR_ENABLE_PFR) && (ZEROERR_CXX_STANDARD >= 14)
13#include "pfr.hpp"
14#endif
15
16#if defined(ZEROERR_ENABLE_MAGIC_ENUM) && (ZEROERR_CXX_STANDARD >= 17)
17#include "magic_enum.hpp"
18#endif
19
20#if defined(ZEROERR_ENABLE_DSVIZ)
21#include "dsviz.h"
22#endif
23
25
26
27namespace zeroerr {
28
29
30constexpr unsigned max_rank = 5;
31
32
33struct Printer;
34template <typename T>
35void PrinterExt(Printer&, T, unsigned, const char*, rank<0>);
36
37namespace detail {
38
42template <typename T, typename = void>
43struct has_extension : std::false_type {};
44
45template <typename T>
49
50template <typename T>
51struct has_extension<T, has_printer_ext<T>> : std::true_type {};
52
53} // namespace detail
54
55
63struct Printer {
64 template <typename... Args>
65 Printer& operator()(Args&&... args) {
67 call(std::forward<Args>(args)...);
68 return *this;
69 }
70 template <typename T>
71 Printer& operator()(std::initializer_list<T>&& value) {
73 call(std::forward<decltype(value)>(value));
74 return *this;
75 }
76
77 void check_stream() {
79 auto& ss = static_cast<std::stringstream&>(os);
80 ss.str(std::string());
81 ss.clear();
82 }
83 }
84
85 template <typename T, typename... V>
86 void call(T value, V... others) {
87 PrinterExt(*this, std::forward<T>(value), 0, " ", rank<max_rank>{});
88 call(std::forward<V>(others)...);
89 }
90
91 template <typename T>
92 void call(T value) {
93 PrinterExt(*this, std::forward<T>(value), 0, "", rank<max_rank>{});
94 os << line_break;
95 os.flush();
96 }
97
98 Printer(std::ostream& os) : os(os) {}
99 Printer() : os(*new std::stringstream()) { use_stringstream = true; }
101 if (use_stringstream) delete &os;
102 }
103
104 bool isColorful = true; // colorful output
105 bool isCompact = false; // compact mode
106 bool isQuoted = true; // string is quoted
107 int indent = 2;
108 const char* line_break = "\n";
109 std::ostream& os;
110 bool use_stringstream = false;
112
113 template <class T>
114 static std::string type(const T& t) {
115 return demangle(typeid(t).name());
116 }
117
118
120 print(T value, unsigned level, const char* lb, rank<0>) { os << tab(level) << value << lb; }
121
123 print(T value, unsigned level, const char* lb, rank<0>) {
124 if (value == nullptr)
125 os << tab(level) << "nullptr" << lb;
126 else
127 os << tab(level) << "<" << type(value) << " at " << value << ">" << lb;
128 }
129
130
132 print(T value, unsigned level, const char* lb, rank<0>) {
133 os << tab(level) << type(value) << lb;
134 }
135
136
138 print(T value, unsigned level, const char* lb, rank<1>) {
139 os << tab(level) << '\'' << value << '\'' << lb;
140 }
141
142#if defined(ZEROERR_ENABLE_PFR) && (ZEROERR_CXX_STANDARD >= 14)
143 template <class StructType, unsigned... I>
144 void print_struct(const StructType& s, unsigned, const char*, detail::seq<I...>) {
145 int _[] = {(os << (I == 0 ? "" : ", ") << pfr::get<I>(s), 0)...};
146 (void)_;
147 }
148
150 print(const T& value, unsigned level, const char* lb, rank<1>) {
151 os << tab(level) << "{";
152 print_struct(value, level, isCompact ? " " : line_break,
153 detail::gen_seq<pfr::tuple_size<T>::value>{});
154 os << tab(level) << "}" << lb;
155 }
156#endif
157
159 print(T value, unsigned level, const char* lb, rank<2>) {
160 os << tab(level) << (value ? "true" : "false") << lb;
161 }
162
164 print(T value, unsigned level, const char* lb, rank<2>) { os << tab(level) << value << lb; }
165
166
168 print(const T& value, unsigned level, const char* lb, rank<2>) {
169 os << tab(level) << "{" << (isCompact ? "" : line_break);
170 bool last = false;
171 for (auto iter = value.begin(); iter != value.end(); ++iter) {
172 if (std::next(iter) == value.end()) last = true;
173 print(*iter, level + 1, isCompact ? (last ? "" : ", ") : line_break, rank<max_rank>{});
174 }
175 os << tab(level) << "}" << lb;
176 }
177
179 print(const T& value, unsigned level, const char* lb, rank<3>) {
180 os << tab(level) << "[";
181 bool last = false;
182 for (auto iter = value.begin(); iter != value.end(); ++iter) {
183 if (std::next(iter) == value.end()) last = true;
184 print(*iter, 0, last ? "" : ", ", rank<max_rank>{});
185 }
186 os << tab(level) << "]" << lb;
187 }
188
189
191 print(T value, unsigned level, const char* lb, rank<3>) {
192 if (value.get() == nullptr)
193 os << tab(level) << "nullptr" << lb;
194 else
195 os << tab(level) << "<" << type(value) << " at " << value.get() << ">" << lb;
196 }
197
199 print(const T& value, unsigned level, const char* lb, rank<4>) {
200 os << tab(level) << "{" << (isCompact ? "" : line_break);
201 bool last = false;
202 for (auto iter = value.begin(); iter != value.end(); ++iter) {
203 if (std::next(iter) == value.end()) last = true;
204 print(iter->first, level + 1, " : ", rank<max_rank>{});
205 print(iter->second, level + 1, isCompact ? (last ? "" : ", ") : line_break,
207 }
208 os << tab(level) << "}" << lb;
209 }
210
212 print(T value, unsigned level, const char* lb, rank<4>) {
213 os << tab(level) << "(" << value.real() << "+" << value.imag() << "i)" << lb;
214 }
215
217 print(T value, unsigned level, const char* lb, rank<4>) {
218 os << tab(level) << quote() << value << quote() << lb;
219 }
220
221 template <class TupType>
222 inline void print_tuple(const TupType&, unsigned, const char*, detail::seq<>) {}
223
224 template <class TupType, unsigned... I>
225 inline void print_tuple(const TupType& _tup, unsigned level, const char*, detail::seq<I...>) {
226 int _[] = {(os << (I == 0 ? "" : ", "),
227 print(std::get<I>(_tup), level + 1, "", rank<max_rank>{}), 0)...};
228 (void)_;
229 }
230
231 template <class... Args>
232 void print(const std::tuple<Args...>& value, unsigned level, const char* lb, rank<3>) {
233 os << tab(level) << "(";
234 print_tuple(value, level, isCompact ? " " : line_break, detail::gen_seq<sizeof...(Args)>{});
235 os << ")" << lb;
236 }
237
238 std::string tab(unsigned level) { return std::string((isCompact ? 0 : level * indent), ' '); }
239 const char* quote() { return isQuoted ? "\"" : ""; }
240
241 static std::string demangle(const char* name) {
242#ifdef __GNUG__
243 int status = -4;
244 char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
245 std::string ret = (status == 0) ? res : name;
246 std::free(res);
247 return ret;
248#else
249 return name;
250#endif
251 }
252
253 std::string str() const {
254 if (use_stringstream == false)
255 throw std::runtime_error("Printer is not using stringstream");
256 return static_cast<std::stringstream&>(os).str();
257 }
258 operator std::string() const { return str(); }
259
260 friend std::ostream& operator<<(std::ostream& os, const Printer& P) {
261 if (P.use_stringstream) os << P.str();
262 return os;
263 }
264};
265
282template <class T>
283void PrinterExt(Printer& P, T v, unsigned level, const char* lb, rank<0>) {
284 P.print(std::forward<T>(v), level, lb, rank<max_rank>{});
285}
286
287extern Printer& getStdoutPrinter();
288extern Printer& getStderrPrinter();
289
290
291} // namespace zeroerr
292
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:218
STL namespace.
void_t< decltype(zeroerr::PrinterExt(std::declval< zeroerr::Printer & >(), std::declval< T & >(), 0, nullptr, zeroerr::rank< zeroerr::max_rank >()))> has_printer_ext
Definition print.h:48
void void_t
Definition typetraits.h:55
Definition benchmark.cpp:17
Printer & getStderrPrinter()
Definition print.cpp:12
void PrinterExt(Printer &, T, unsigned, const char *, rank< 0 >)
PrinterExt is an extension of Printer that allows user to write custom rules for printing.
Definition print.h:283
Printer & getStdoutPrinter()
Definition print.cpp:7
constexpr unsigned max_rank
Definition print.h:30
A functor class Printer for printing a value of any type.
Definition print.h:63
Printer()
Definition print.h:99
int indent
Definition print.h:107
bool clear_stream_before_printing
Definition print.h:111
Printer & operator()(Args &&... args)
Definition print.h:65
~Printer()
Definition print.h:100
void print(const std::tuple< Args... > &value, unsigned level, const char *lb, rank< 3 >)
Definition print.h:232
void print_tuple(const TupType &, unsigned, const char *, detail::seq<>)
Definition print.h:222
std::ostream & os
Definition print.h:109
bool isColorful
Definition print.h:104
static std::string demangle(const char *name)
Definition print.h:241
bool isQuoted
Definition print.h:106
static std::string type(const T &t)
Definition print.h:114
const char * quote()
Definition print.h:239
std::string str() const
Definition print.h:253
bool isCompact
Definition print.h:105
std::string tab(unsigned level)
Definition print.h:238
Printer & operator()(std::initializer_list< T > &&value)
Definition print.h:71
Printer(std::ostream &os)
Definition print.h:98
void call(T value)
Definition print.h:92
void check_stream()
Definition print.h:77
print(T value, unsigned level, const char *lb, rank< 0 >)
Definition print.h:120
void print_tuple(const TupType &_tup, unsigned level, const char *, detail::seq< I... >)
Definition print.h:225
bool use_stringstream
Definition print.h:110
const char * line_break
Definition print.h:108
void call(T value, V... others)
Definition print.h:86
friend std::ostream & operator<<(std::ostream &os, const Printer &P)
Definition print.h:260
Definition typetraits.h:77
has_extension is a type trait to check if user defined PrinterExt for a type
Definition print.h:43
Definition typetraits.h:74
Definition dbg.h:21
rank is a helper class for Printer to define the priority of overloaded functions.
Definition typetraits.h:46
#define ZEROERR_IS_MAP
Definition typetraits.h:293
#define ZEROERR_IS_CONTAINER
Definition typetraits.h:279
#define ZEROERR_IS_POD
Definition typetraits.h:294
#define ZEROERR_IS_FLOAT
Definition typetraits.h:278
#define ZEROERR_IS_INT
Definition typetraits.h:277
#define ZEROERR_IS_POINTER
Definition typetraits.h:281
#define ZEROERR_IS_CLASS
Definition typetraits.h:284
#define ZEROERR_IS_STREAMABLE
Definition typetraits.h:285
#define ZEROERR_IS_CHAR
Definition typetraits.h:282
#define ZEROERR_IS_WCHAR
Definition typetraits.h:283
#define ZEROERR_IS_STRING
Definition typetraits.h:280
#define ZEROERR_IS_AUTOPTR
Definition typetraits.h:289
#define ZEROERR_IS_COMPLEX
Definition typetraits.h:287
#define ZEROERR_IS_BOOL
Definition typetraits.h:288
#define ZEROERR_ENABLE_IF(x)
Definition typetraits.h:274
#define ZEROERR_IS_ARRAY
Definition typetraits.h:286