ZeroErr
载入中...
搜索中...
未找到
print.h
浏览该文件的文档.
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#if defined(ZEROERR_ENABLE_MAGIC_ENUM) && (ZEROERR_CXX_STANDARD >= 17)
119 print(T value, unsigned level, const char* lb, rank<0>) { os << tab(level) << magic_enum::enum_name(value) << lb; }
120#else
122 print(T value, unsigned level, const char* lb, rank<0>) { os << tab(level) << value << lb; }
123#endif
124
126 print(T value, unsigned level, const char* lb, rank<0>) { os << tab(level) << value << lb; }
127
129 print(T value, unsigned level, const char* lb, rank<0>) {
130 if (value == nullptr)
131 os << tab(level) << "nullptr" << lb;
132 else
133 os << tab(level) << "<" << type(value) << " at " << static_cast<const void*>(value) << ">" << lb;
134 }
135
136
138 print(T value, unsigned level, const char* lb, rank<0>) {
139 os << tab(level) << type(value) << lb;
140 }
141
142
144 print(T value, unsigned level, const char* lb, rank<1>) {
145 os << tab(level) << '\'' << value << '\'' << lb;
146 }
147
148#if defined(ZEROERR_ENABLE_PFR) && (ZEROERR_CXX_STANDARD >= 14)
149 template <class StructType, unsigned... I>
150 void print_struct(const StructType& s, unsigned, const char*, detail::seq<I...>) {
151 int _[] = {(os << (I == 0 ? "" : ", ") << pfr::get<I>(s), 0)...};
152 (void)_;
153 }
154
156 print(const T& value, unsigned level, const char* lb, rank<1>) {
157 os << tab(level) << "{";
158 print_struct(value, level, isCompact ? " " : line_break,
159 detail::gen_seq<pfr::tuple_size<T>::value>{});
160 os << tab(level) << "}" << lb;
161 }
162#endif
163
165 print(T value, unsigned level, const char* lb, rank<2>) {
166 os << tab(level) << (value ? "true" : "false") << lb;
167 }
168
170 print(T value, unsigned level, const char* lb, rank<2>) { os << tab(level) << value << lb; }
171
172
174 print(const T& value, unsigned level, const char* lb, rank<2>) {
175 os << tab(level) << "{" << (isCompact ? "" : line_break);
176 bool last = false;
177 for (auto iter = value.begin(); iter != value.end(); ++iter) {
178 if (std::next(iter) == value.end()) last = true;
179 print(*iter, level + 1, isCompact ? (last ? "" : ", ") : line_break, rank<max_rank>{});
180 }
181 os << tab(level) << "}" << lb;
182 }
183
185 print(const T& value, unsigned level, const char* lb, rank<3>) {
186 os << tab(level) << "[";
187 bool last = false;
188 for (auto iter = value.begin(); iter != value.end(); ++iter) {
189 if (std::next(iter) == value.end()) last = true;
190 print(*iter, 0, last ? "" : ", ", rank<max_rank>{});
191 }
192 os << tab(level) << "]" << lb;
193 }
194
195
197 print(T value, unsigned level, const char* lb, rank<3>) {
198 if (value.get() == nullptr)
199 os << tab(level) << "nullptr" << lb;
200 else
201 os << tab(level) << "<" << type(value) << " at " << value.get() << ">" << lb;
202 }
203
205 print(const T& value, unsigned level, const char* lb, rank<4>) {
206 os << tab(level) << "{" << (isCompact ? "" : line_break);
207 bool last = false;
208 for (auto iter = value.begin(); iter != value.end(); ++iter) {
209 if (std::next(iter) == value.end()) last = true;
210 print(iter->first, level + 1, " : ", rank<max_rank>{});
211 print(iter->second, level + 1, isCompact ? (last ? "" : ", ") : line_break,
213 }
214 os << tab(level) << "}" << lb;
215 }
216
218 print(T value, unsigned level, const char* lb, rank<4>) {
219 os << tab(level) << "(" << value.real() << "+" << value.imag() << "i)" << lb;
220 }
221
223 print(T value, unsigned level, const char* lb, rank<4>) {
224 os << tab(level) << quote() << value << quote() << lb;
225 }
226
227 template <class TupType>
228 inline void print_tuple(const TupType&, unsigned, const char*, detail::seq<>) {}
229
230 template <class TupType, unsigned... I>
231 inline void print_tuple(const TupType& _tup, unsigned level, const char*, detail::seq<I...>) {
232 int _[] = {(os << (I == 0 ? "" : ", "),
233 print(std::get<I>(_tup), level + 1, "", rank<max_rank>{}), 0)...};
234 (void)_;
235 }
236
237 template <class... Args>
238 void print(const std::tuple<Args...>& value, unsigned level, const char* lb, rank<3>) {
239 os << tab(level) << "(";
240 print_tuple(value, level, isCompact ? " " : line_break, detail::gen_seq<sizeof...(Args)>{});
241 os << ")" << lb;
242 }
243
244 std::string tab(unsigned level) { return std::string((isCompact ? 0 : level * indent), ' '); }
245 const char* quote() { return isQuoted ? "\"" : ""; }
246
247 static std::string demangle(const char* name) {
248#ifdef __GNUG__
249 int status = -4;
250 char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
251 std::string ret = (status == 0) ? res : name;
252 std::free(res);
253 return ret;
254#else
255 return name;
256#endif
257 }
258
259 std::string str() const {
260 if (use_stringstream == false)
261 throw std::runtime_error("Printer is not using stringstream");
262 return static_cast<std::stringstream&>(os).str();
263 }
264 operator std::string() const { return str(); }
265
266 friend std::ostream& operator<<(std::ostream& os, const Printer& P) {
267 if (P.use_stringstream) os << P.str();
268 return os;
269 }
270};
271
288template <class T>
289void PrinterExt(Printer& P, T v, unsigned level, const char* lb, rank<0>) {
290 P.print(std::forward<T>(v), level, lb, rank<max_rank>{});
291}
292
293extern Printer& getStdoutPrinter();
294extern Printer& getStderrPrinter();
295
296
297} // namespace zeroerr
298
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:268
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:220
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:289
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:238
void print_tuple(const TupType &, unsigned, const char *, detail::seq<>)
Definition print.h:228
std::ostream & os
Definition print.h:108
bool isColorful
Definition print.h:103
static std::string demangle(const char *name)
Definition print.h:247
bool isQuoted
Definition print.h:105
static std::string type(const T &t)
Definition print.h:113
const char * quote()
Definition print.h:245
std::string str() const
Definition print.h:259
bool isCompact
Definition print.h:104
std::string tab(unsigned level)
Definition print.h:244
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:122
void print_tuple(const TupType &_tup, unsigned level, const char *, detail::seq< I... >)
Definition print.h:231
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:266
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:280
#define ZEROERR_IS_ENUM
Definition typetraits.h:265
#define ZEROERR_IS_CONTAINER
Definition typetraits.h:266
#define ZEROERR_IS_POD
Definition typetraits.h:281
#define ZEROERR_IS_FLOAT
Definition typetraits.h:264
#define ZEROERR_IS_INT
Definition typetraits.h:263
#define ZEROERR_IS_POINTER
Definition typetraits.h:268
#define ZEROERR_IS_CLASS
Definition typetraits.h:271
#define ZEROERR_IS_STREAMABLE
Definition typetraits.h:272
#define ZEROERR_IS_CHAR
Definition typetraits.h:269
#define ZEROERR_IS_WCHAR
Definition typetraits.h:270
#define ZEROERR_IS_STRING
Definition typetraits.h:267
#define ZEROERR_IS_AUTOPTR
Definition typetraits.h:276
#define ZEROERR_IS_COMPLEX
Definition typetraits.h:274
#define ZEROERR_IS_BOOL
Definition typetraits.h:275
#define ZEROERR_ENABLE_IF(x)
Definition typetraits.h:260
#define ZEROERR_IS_ARRAY
Definition typetraits.h:273