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