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