ZeroErr
载入中...
搜索中...
未找到
print.h
浏览该文件的文档.
1#pragma once
2
3// libc++ offers compatibility-only transitive includes through C++20.
4// Suppress those while loading our explicit dependencies, then restore the
5// caller's setting. This does not change standard-library types or ABI.
6#pragma push_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
7#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
8#define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
9#endif
10
12
13#include "zeroerr/color.h"
15#include "zeroerr/buffer.h"
17#include <functional>
18
19#include <memory>
20#include <initializer_list>
21#include <typeinfo>
22
23#if defined(ZEROERR_ENABLE_PFR) && (ZEROERR_CXX_STANDARD >= 14)
24#include "pfr.hpp"
25#endif
26
27#if defined(ZEROERR_ENABLE_MAGIC_ENUM) && (ZEROERR_CXX_STANDARD >= 17)
28#include "magic_enum.hpp"
29#endif
30
31#if defined(ZEROERR_ENABLE_DSVIZ)
32#include "dsviz.h"
33#endif
34
36
37
38namespace zeroerr {
39
40
41constexpr unsigned max_rank = 5;
42
43
44struct Printer;
45template <typename T>
46void PrinterExt(Printer&, const T&, unsigned, const char*, rank<0>);
47
48namespace detail {
49
53template <typename T, typename = void>
54struct has_extension : std::false_type {};
55
56template <typename T>
60
61template <typename T>
62struct has_extension<T, has_printer_ext<T>> : std::true_type {};
63
64} // namespace detail
65
66
74struct Printer {
75 template <typename... Args>
76 Printer& operator()(Args&&... args) {
78 call(std::forward<Args>(args)...);
79 return *this;
80 }
81 template <typename T>
82 Printer& operator()(std::initializer_list<T>&& value) {
84 call(std::forward<decltype(value)>(value));
85 return *this;
86 }
87
91
92 template <typename T, typename... V>
93 void call(T&& value, V&&... others) {
94 PrinterExt(*this, std::forward<T>(value), 0, " ", rank<max_rank>{});
95 call(std::forward<V>(others)...);
96 }
97
98 template <typename T>
99 void call(T&& value) {
100 PrinterExt(*this, std::forward<T>(value), 0, "", rank<max_rank>{});
101 os << line_break;
102 os.flush();
103 }
104
105private:
106 StringBuffer storage_;
107public:
108 Printer() : os(storage_) { use_stringstream = true; }
109 template <class Stream>
110 explicit Printer(Stream& stream) : os(storage_) { storage_.attach(stream); }
111 Printer(const Printer& other) : storage_(other.storage_), isColorful(other.isColorful),
112 isCompact(other.isCompact), isQuoted(other.isQuoted), indent(other.indent),
113 line_break(other.line_break), os(storage_), use_stringstream(other.use_stringstream),
115
116 bool isColorful = true; // colorful output
117 bool isCompact = false; // compact mode
118 bool isQuoted = true; // string is quoted
119 int indent = 2;
120 const char* line_break = "\n";
122 bool use_stringstream = false;
124
125 template <class T>
126 static zeroerr::String type(const T& t) {
127 return demangle(typeid(t).name());
128 }
129
130#if defined(ZEROERR_ENABLE_MAGIC_ENUM) && (ZEROERR_CXX_STANDARD >= 17)
132 print(const T& value, unsigned level, const char* lb, rank<0>) { os << tab(level) << magic_enum::enum_name(value) << lb; }
133#else
135 print(const T& value, unsigned level, const char* lb, rank<0>) {
137 os << tab(level) << value << lb;
138 } else {
139 os << tab(level) << "<unprintable enum " << type(value) << ">" << lb;
140 }
141 }
142#endif
143
145 print(const T& value, unsigned level, const char* lb, rank<0>) { os << tab(level) << value << lb; }
146
148 !std::is_function<typename std::remove_pointer<T>::type>::value)
149 print(const T& value, unsigned level, const char* lb, rank<0>) {
150 if (value == nullptr)
151 os << tab(level) << "nullptr" << lb;
152 else
153 os << tab(level) << "<" << type(value) << " at " << static_cast<const void*>(value) << ">" << lb;
154 }
155
157 std::is_function<typename std::remove_pointer<T>::type>::value)
158 print(T value, unsigned level, const char* lb, rank<1>) {
159 if (value == nullptr)
160 os << tab(level) << "nullptr" << lb;
161 else
162 os << tab(level) << "<" << type(value) << " at "
163 << reinterpret_cast<const void*>(value) << ">" << lb;
164 }
165
166 template <class R, class... Args>
167 void print(const std::function<R(Args...)>& value, unsigned level, const char* lb, rank<3>) {
168 if (!value)
169 os << tab(level) << "nullptr" << lb;
170 else
171 os << tab(level) << "<" << type(value) << " holding "
172 << demangle(value.target_type().name()) << ">" << lb;
173 }
174
175
176 // Preserve the pointer fallback for built-in arrays; character arrays use
177 // the higher-priority string rule.
178 template <typename T, std::size_t N>
179 void print(const T (&value)[N], unsigned level, const char* lb, rank<0>) {
180 print(value + 0, level, lb, rank<max_rank>{});
181 }
182
184 print(const T& value, unsigned level, const char* lb, rank<0>) {
185 os << tab(level) << type(value) << lb;
186 }
187
188
190 print(const T& value, unsigned level, const char* lb, rank<1>) {
191 os << tab(level) << '\'' << value << '\'' << lb;
192 }
193
194#if defined(ZEROERR_ENABLE_PFR) && (ZEROERR_CXX_STANDARD >= 14)
195 template <class StructType, unsigned... I>
196 void print_struct(const StructType& s, unsigned, const char*, detail::seq<I...>) {
197 int _[] = {(os << (I == 0 ? "" : ", ") << pfr::get<I>(s), 0)...};
198 (void)_;
199 }
200
202 print(const T& value, unsigned level, const char* lb, rank<1>) {
203 os << tab(level) << "{";
204 print_struct(value, level, isCompact ? " " : line_break,
205 detail::gen_seq<pfr::tuple_size<T>::value>{});
206 os << tab(level) << "}" << lb;
207 }
208#endif
209
211 print(const T& value, unsigned level, const char* lb, rank<2>) {
212 os << tab(level) << (value ? "true" : "false") << lb;
213 }
214
216 print(const T& value, unsigned level, const char* lb, rank<2>) { os << tab(level) << value << lb; }
217
218
220 print(const T& value, unsigned level, const char* lb, rank<2>) {
221 os << tab(level) << "{" << (isCompact ? "" : line_break);
222 bool last = false;
223 for (auto iter = value.begin(); iter != value.end(); ++iter) {
224 auto next = iter;
225 ++next;
226 if (next == value.end()) last = true;
227 print(*iter, level + 1, isCompact ? (last ? "" : ", ") : line_break, rank<max_rank>{});
228 }
229 os << tab(level) << "}" << lb;
230 }
231
233 print(const T& value, unsigned level, const char* lb, rank<3>) {
234 os << tab(level) << "[";
235 bool last = false;
236 for (auto iter = value.begin(); iter != value.end(); ++iter) {
237 auto next = iter;
238 ++next;
239 if (next == value.end()) last = true;
240 print(*iter, 0, last ? "" : ", ", rank<max_rank>{});
241 }
242 os << tab(level) << "]" << lb;
243 }
244
245
247 print(const T& value, unsigned level, const char* lb, rank<3>) {
248 if (value.get() == nullptr)
249 os << tab(level) << "nullptr" << lb;
250 else
251 os << tab(level) << "<" << type(value) << " at " << static_cast<const void*>(value.get()) << ">" << lb;
252 }
253
255 !ZEROERR_IS_COMPLEX && !detail::is_weak_pointer_like<T>::value)
256 print(const T& value, unsigned level, const char* lb, rank<4>) {
257 os << tab(level) << "{" << (isCompact ? "" : line_break);
258 bool last = false;
259 for (auto iter = value.begin(); iter != value.end(); ++iter) {
260 auto next = iter;
261 ++next;
262 if (next == value.end()) last = true;
263 print((*iter).first, level + 1, " : ", rank<max_rank>{});
264 print((*iter).second, level + 1, isCompact ? (last ? "" : ", ") : line_break,
265 rank<max_rank>{});
266 }
267 os << tab(level) << "}" << lb;
268 }
269
270 ZEROERR_ENABLE_IF(detail::is_weak_pointer_like<T>::value && !ZEROERR_IS_STRING && !ZEROERR_IS_COMPLEX)
271 print(const T& value, unsigned level, const char* lb, rank<4>) {
272 const auto locked = value.lock();
273 print(locked, level, lb, rank<3>{});
274 }
275
277 print(const T& value, unsigned level, const char* lb, rank<4>) {
278 os << tab(level) << "(" << value.real() << "+" << value.imag() << "i)" << lb;
279 }
280
282 print(const T& value, unsigned level, const char* lb, rank<4>) {
283 os << tab(level) << quote();
284 write_string(value, typename detail::is_string_like<T>::type{});
285 os << quote() << lb;
286 }
287
288 template <class T>
289 void write_string(const T& value, std::true_type) {
290 if (value.size() != 0)
291 os.write(value.data(), static_cast<std::size_t>(value.size()));
292 }
293 template <class T>
294 void write_string(const T& value, std::false_type) {
295 const char* text = value;
296 os << (text ? text : "nullptr");
297 }
298
299 template <class TupType>
300 inline void print_tuple(const TupType&, unsigned, const char*, detail::seq<>) {}
301
302 template <class TupType, unsigned... I>
303 inline void print_tuple(const TupType& _tup, unsigned level, const char*, detail::seq<I...>) {
304 int _[] = {(os << (I == 0 ? "" : ", "),
305 print(detail::tuple_get<I>(_tup), level + 1, "", rank<max_rank>{}), 0)...};
306 (void)_;
307 }
308
309 ZEROERR_ENABLE_IF(detail::is_tuple_like<T>::value && !ZEROERR_IS_CONTAINER && !ZEROERR_IS_AUTOPTR)
310 print(const T& value, unsigned level, const char* lb, rank<3>) {
311 os << tab(level) << "(";
312 print_tuple(value, level, isCompact ? " " : line_break, detail::gen_seq<std::tuple_size<T>::value>{});
313 os << ")" << lb;
314 }
315
316 void print_text(const char* value) { os << value; }
317 template <class T> void print_text(const T& value) { os.write(value.data(), value.size()); }
318 zeroerr::String tab(unsigned level);
319 const char* quote() { return isQuoted ? "\"" : ""; }
320
321 static zeroerr::String demangle(const char* name);
322
323 zeroerr::String str() const;
324 operator zeroerr::String() const { return str(); }
325 template <class T, typename std::enable_if<detail::StringLike<T>::owning &&
326 !std::is_same<T, String>::value, int>::type = 0>
327 operator T() const { return str(); }
328
329};
330
331inline StringBuffer& operator<<(StringBuffer& buffer, const Printer& printer) {
332 if (printer.use_stringstream) buffer << printer.str();
333 return buffer;
334}
335
336namespace detail {
337
338// Only the concrete value dispatch is templated. Stream construction, printing
339// order, formatting and cleanup all live in the shared implementation.
340template <typename T>
341void printDiagnosticValue(Printer& printer, const void* value) {
342 printer.call(*static_cast<T*>(const_cast<void*>(value)));
343}
344
345template <typename T>
347 return {const_cast<const void*>(static_cast<const volatile void*>(std::addressof(value))),
348 &printDiagnosticValue<T>};
349}
350
351} // namespace detail
352
369template <class T>
370void PrinterExt(Printer& P, const T& v, unsigned level, const char* lb, rank<0>) {
371 P.print(v, level, lb, rank<max_rank>{});
372}
373
374extern Printer& getStdoutPrinter();
375extern Printer& getStderrPrinter();
376
377
378} // namespace zeroerr
379
381
382#pragma pop_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
Definition buffer.h:7
void clear()
Definition buffer.h:35
void attach(Stream &stream)
Definition buffer.h:18
StringBuffer & write(const char *data, std::size_t size)
Definition buffer.cpp:5
void flush()
Definition buffer.cpp:12
Definition string.h:41
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:283
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:235
STL namespace
void printDiagnosticValue(Printer &printer, const void *value)
Definition print.h:341
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:59
void void_t
Definition typetraits.h:55
DiagnosticValue makeDiagnosticValue(T &value)
Definition print.h:346
Definition assert_text.cpp:5
StringBuffer & operator<<(StringBuffer &buffer, const Printer &printer)
Definition print.h:331
Printer & getStderrPrinter()
Definition print.cpp:14
void PrinterExt(Printer &, const T &, unsigned, const char *, rank< 0 >)
PrinterExt is an extension of Printer that allows user to write custom rules for printing.
Definition print.h:370
Printer & getStdoutPrinter()
Definition print.cpp:9
constexpr unsigned max_rank
Definition print.h:41
A functor class Printer for printing a value of any type.
Definition print.h:74
Printer()
Definition print.h:108
int indent
Definition print.h:119
print(const T &value, unsigned level, const char *lb, rank< 0 >)
Definition print.h:135
bool clear_stream_before_printing
Definition print.h:123
unsigned const char * lb
Definition print.h:149
Printer & operator()(Args &&... args)
Definition print.h:76
Printer(const Printer &other)
Definition print.h:111
StringBuffer & os
Definition print.h:121
bool isColorful
Definition print.h:116
unsigned const char rank< 0 >
Definition print.h:149
bool isQuoted
Definition print.h:118
void call(T &&value, V &&... others)
Definition print.h:93
static zeroerr::String type(const T &t)
Definition print.h:126
bool isCompact
Definition print.h:117
Printer(Stream &stream)
Definition print.h:110
Printer & operator()(std::initializer_list< T > &&value)
Definition print.h:82
void call(T &&value)
Definition print.h:99
void check_stream()
Definition print.h:88
ZEROERR_ENABLE_IF(ZEROERR_IS_POINTER &&!std::is_function< typename std::remove_pointer< T >::type >::value) print(const T &value
bool use_stringstream
Definition print.h:122
const char * line_break
Definition print.h:120
unsigned level
Definition print.h:149
has_extension is a type trait to check if user defined PrinterExt for a type
Definition print.h:54
Definition typetraits.h:97
rank is a helper class for Printer to define the priority of overloaded functions.
Definition typetraits.h:43
#define last
Definition table.cpp:255
#define ZEROERR_IS_MAP
Definition typetraits.h:351
#define ZEROERR_IS_ENUM
Definition typetraits.h:339
#define ZEROERR_IS_CONTAINER
Definition typetraits.h:340
#define ZEROERR_IS_POD
Definition typetraits.h:352
#define ZEROERR_IS_FLOAT
Definition typetraits.h:338
#define ZEROERR_IS_INT
Definition typetraits.h:337
#define ZEROERR_IS_POINTER
Definition typetraits.h:342
#define ZEROERR_IS_CLASS
Definition typetraits.h:345
#define ZEROERR_IS_STREAMABLE
Definition typetraits.h:346
#define ZEROERR_IS_CHAR
Definition typetraits.h:343
#define ZEROERR_IS_WCHAR
Definition typetraits.h:344
#define ZEROERR_IS_STRING
Definition typetraits.h:341
#define ZEROERR_IS_AUTOPTR
Definition typetraits.h:350
#define ZEROERR_IS_COMPLEX
Definition typetraits.h:348
#define ZEROERR_IS_BOOL
Definition typetraits.h:349
#define ZEROERR_ENABLE_IF(x)
Definition typetraits.h:334
#define ZEROERR_IS_ARRAY
Definition typetraits.h:347