souffle  2.0.2-371-g6315b36
StreamUtil.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file StreamUtil.h
12  *
13  * @brief Datalog project utilities
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include <map>
20 #include <memory>
21 #include <ostream>
22 #include <set>
23 #include <string>
24 #include <type_traits>
25 #include <utility>
26 #include <vector>
27 
29 #include "souffle/utility/span.h"
30 
31 // -------------------------------------------------------------------------------
32 // General Print Utilities
33 // -------------------------------------------------------------------------------
34 
35 namespace souffle {
36 
37 // Usage: `using namespace stream_write_qualified_char_as_number;`
38 // NB: `using` must appear in the same namespace as the `<<` callers.
39 // Putting the `using` in a parent namespace will have no effect.
40 // Motivation: Octet sized numeric types are often defined as aliases of a qualified
41 // `char`. e.g. `using uint8_t = unsigned char'`
42 // `std::ostream` has an overload which converts qualified `char`s to plain `char`.
43 // You don't usually want to print a `uint8_t` as an ASCII character.
44 //
45 // NOTE: `char`, `signed char`, and `unsigned char` are distinct types.
46 namespace stream_write_qualified_char_as_number {
47 inline std::ostream& operator<<(std::ostream& os, signed char c) {
48  return os << int(c);
49 }
50 
51 inline std::ostream& operator<<(std::ostream& os, unsigned char c) {
52  return os << unsigned(c);
53 }
54 } // namespace stream_write_qualified_char_as_number
55 
56 template <typename A>
57 struct IsPtrLike : std::is_pointer<A> {};
58 template <typename A>
59 struct IsPtrLike<Own<A>> : std::true_type {};
60 template <typename A>
61 struct IsPtrLike<std::shared_ptr<A>> : std::true_type {};
62 template <typename A>
63 struct IsPtrLike<std::weak_ptr<A>> : std::true_type {};
64 
65 namespace detail {
66 
67 /**
68  * A auxiliary class to be returned by the join function aggregating the information
69  * required to print a list of elements as well as the implementation of the printing
70  * itself.
71  */
72 template <typename Iter, typename Printer>
73 class joined_sequence {
74  /** The begin of the range to be printed */
75  Iter begin;
76 
77  /** The end of the range to be printed */
78  Iter end;
79 
80  /** The seperator to be utilized between elements */
81  std::string sep;
82 
83  /** A functor printing an element */
84  Printer p;
85 
86 public:
87  /** A constructor setting up all fields of this class */
88  joined_sequence(const Iter& a, const Iter& b, std::string sep, Printer p)
89  : begin(a), end(b), sep(std::move(sep)), p(std::move(p)) {}
90 
91  /** The actual print method */
92  friend std::ostream& operator<<(std::ostream& out, const joined_sequence& s) {
93  auto cur = s.begin;
94  if (cur == s.end) {
95  return out;
96  }
97 
98  s.p(out, *cur);
99  ++cur;
100  for (; cur != s.end; ++cur) {
101  out << s.sep;
102  s.p(out, *cur);
103  }
104  return out;
105  }
106 };
107 
108 /**
109  * A generic element printer.
110  *
111  * @tparam Extractor a functor preparing a given value before being printed.
112  */
113 template <typename Extractor>
114 struct print {
115  template <typename T>
116  void operator()(std::ostream& out, const T& value) const {
117  // extract element to be printed from the given value and print it
118  Extractor ext;
119  out << ext(value);
120  }
121 };
122 } // namespace detail
123 
124 /**
125  * A functor representing the identity function for a generic type T.
126  *
127  * @tparam T some arbitrary type
128  */
129 template <typename T>
130 struct id {
131  T& operator()(T& t) const {
132  return t;
133  }
134  const T& operator()(const T& t) const {
135  return t;
136  }
137 };
138 
139 /**
140  * A functor dereferencing a given type
141  *
142  * @tparam T some arbitrary type with an overloaded * operator (deref)
143  */
144 template <typename T>
145 struct deref {
146  auto operator()(T& t) const -> decltype(*t) {
147  return *t;
148  }
149  auto operator()(const T& t) const -> decltype(*t) {
150  return *t;
151  }
152 };
153 
154 /**
155  * A functor printing elements after dereferencing it. This functor
156  * is mainly intended to be utilized when printing sequences of elements
157  * of a pointer type when using the join function below.
158  */
159 template <typename T>
160 struct print_deref : public detail::print<deref<T>> {};
161 
162 /**
163  * Creates an object to be forwarded to some output stream for printing
164  * sequences of elements interspersed by a given separator.
165  *
166  * For use cases see the test case {util_test.cpp}.
167  */
168 template <typename Iter, typename Printer>
170  const Iter& a, const Iter& b, const std::string& sep, const Printer& p) {
172 }
173 
174 /**
175  * Creates an object to be forwarded to some output stream for printing
176  * sequences of elements interspersed by a given separator.
177  *
178  * For use cases see the test case {util_test.cpp}.
179  */
180 template <typename Iter, typename T = typename Iter::value_type>
182  const Iter& a, const Iter& b, const std::string& sep = ",") {
183  return join(a, b, sep, detail::print<id<T>>());
184 }
185 
186 /**
187  * Creates an object to be forwarded to some output stream for printing
188  * the content of containers interspersed by a given separator.
189  *
190  * For use cases see the test case {util_test.cpp}.
191  */
192 template <typename Container, typename Printer, typename Iter = typename Container::const_iterator>
193 detail::joined_sequence<Iter, Printer> join(const Container& c, const std::string& sep, const Printer& p) {
194  return join(c.begin(), c.end(), sep, p);
195 }
196 
197 // Decide if the sane default is to deref-then-print or just print.
198 // Right now, deref anything deref-able *except* for a `const char*` (which handled as a C-string).
199 template <typename A>
200 constexpr bool JoinShouldDeref = IsPtrLike<A>::value && !std::is_same_v<A, char const*>;
201 
202 /**
203  * Creates an object to be forwarded to some output stream for printing
204  * the content of containers interspersed by a given separator.
205  *
206  * For use cases see the test case {util_test.cpp}.
207  */
208 template <typename Container, typename Iter = typename Container::const_iterator,
209  typename T = typename std::iterator_traits<Iter>::value_type>
210 std::enable_if_t<!JoinShouldDeref<T>, detail::joined_sequence<Iter, detail::print<id<T>>>> join(
211  const Container& c, const std::string& sep = ",") {
212  return join(c.begin(), c.end(), sep, detail::print<id<T>>());
213 }
214 
215 template <typename Container, typename Iter = typename Container::const_iterator,
216  typename T = typename std::iterator_traits<Iter>::value_type>
217 std::enable_if_t<JoinShouldDeref<T>, detail::joined_sequence<Iter, detail::print<deref<T>>>> join(
218  const Container& c, const std::string& sep = ",") {
219  return join(c.begin(), c.end(), sep, detail::print<deref<T>>());
220 }
221 
222 } // end namespace souffle
223 
224 #ifndef __EMBEDDED_SOUFFLE__
225 
226 namespace std {
227 
228 /**
229  * Enables the generic printing of `array`s assuming their element types
230  * are printable.
231  */
232 template <typename T, size_t E>
233 ostream& operator<<(ostream& out, const array<T, E>& v) {
234  return out << "[" << souffle::join(v) << "]";
235 }
236 
237 /**
238  * Introduces support for printing pairs as long as their components can be printed.
239  */
240 template <typename A, typename B>
241 ostream& operator<<(ostream& out, const pair<A, B>& p) {
242  return out << "(" << p.first << "," << p.second << ")";
243 }
244 
245 /**
246  * Enables the generic printing of vectors assuming their element types
247  * are printable.
248  */
249 template <typename T, typename A>
250 ostream& operator<<(ostream& out, const vector<T, A>& v) {
251  return out << "[" << souffle::join(v) << "]";
252 }
253 
254 /**
255  * Enables the generic printing of `span`s assuming their element types
256  * are printable.
257  */
258 template <typename T, size_t E>
259 ostream& operator<<(ostream& out, const souffle::span<T, E>& v) {
260  return out << "[" << souffle::join(v) << "]";
261 }
262 
263 /**
264  * Enables the generic printing of sets assuming their element types
265  * are printable.
266  */
267 template <typename K, typename C, typename A>
268 ostream& operator<<(ostream& out, const set<K, C, A>& s) {
269  return out << "{" << souffle::join(s) << "}";
270 }
271 
272 /**
273  * Enables the generic printing of multisets assuming their element types
274  * are printable.
275  */
276 template <typename K, typename C, typename A>
277 ostream& operator<<(ostream& out, const multiset<K, C, A>& s) {
278  return out << "{" << souffle::join(s) << "}";
279 }
280 
281 /**
282  * Enables the generic printing of maps assuming their element types
283  * are printable.
284  */
285 template <typename K, typename T, typename C, typename A>
286 ostream& operator<<(ostream& out, const map<K, T, C, A>& m) {
287  return out << "{" << souffle::join(m, ",", [](ostream& out, const pair<K, T>& cur) {
288  out << cur.first << "->" << cur.second;
289  }) << "}";
290 }
291 
292 } // end namespace std
293 
294 #endif
295 
296 namespace souffle {
297 
298 namespace detail {
299 
300 /**
301  * A utility class required for the implementation of the times function.
302  */
303 template <typename T>
305  const T& value;
306  unsigned times;
307  multiplying_printer(const T& value, unsigned times) : value(value), times(times) {}
308 
309  friend std::ostream& operator<<(std::ostream& out, const multiplying_printer& printer) {
310  for (unsigned i = 0; i < printer.times; i++) {
311  out << printer.value;
312  }
313  return out;
314  }
315 };
316 } // namespace detail
317 
318 /**
319  * A utility printing a given value multiple times.
320  */
321 template <typename T>
322 detail::multiplying_printer<T> times(const T& value, unsigned num) {
323  return detail::multiplying_printer<T>(value, num);
324 }
325 
326 } // namespace souffle
souffle::deref::operator()
auto operator()(T &t) const -> decltype(*t)
Definition: StreamUtil.h:152
souffle::detail::joined_sequence::begin
Iter begin
The begin of the range to be printed.
Definition: StreamUtil.h:81
m
var m
Definition: htmlJsChartistMin.h:15
souffle::span
tcb::span< A, E > span
Definition: span.h:659
souffle::detail::multiplying_printer
A utility class required for the implementation of the times function.
Definition: StreamUtil.h:304
souffle::detail::multiplying_printer::times
unsigned times
Definition: StreamUtil.h:306
souffle::detail::print
A generic element printer.
Definition: StreamUtil.h:120
souffle::id
A functor representing the identity function for a generic type T.
Definition: StreamUtil.h:136
souffle::detail::joined_sequence::p
Printer p
A functor printing an element.
Definition: StreamUtil.h:90
souffle::detail::joined_sequence::sep
std::string sep
The seperator to be utilized between elements.
Definition: StreamUtil.h:87
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::print_deref
A functor printing elements after dereferencing it.
Definition: StreamUtil.h:166
souffle::JoinShouldDeref
constexpr bool JoinShouldDeref
Definition: StreamUtil.h:206
souffle::detail::multiplying_printer::multiplying_printer
multiplying_printer(const T &value, unsigned times)
Definition: StreamUtil.h:307
souffle::times
detail::multiplying_printer< T > times(const T &value, unsigned num)
A utility printing a given value multiple times.
Definition: StreamUtil.h:322
i
size_t i
Definition: json11.h:663
ContainerUtil.h
souffle::IsPtrLike
Definition: StreamUtil.h:63
span.h
souffle::detail::joined_sequence::joined_sequence
joined_sequence(const Iter &a, const Iter &b, std::string sep, Printer p)
A constructor setting up all fields of this class.
Definition: StreamUtil.h:94
souffle::detail::joined_sequence
A auxiliary class to be returned by the join function aggregating the information required to print a...
Definition: StreamUtil.h:79
souffle::join
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Definition: StreamUtil.h:175
souffle::detail::print::operator()
void operator()(std::ostream &out, const T &value) const
Definition: StreamUtil.h:122
souffle::detail::multiplying_printer::value
const T & value
Definition: StreamUtil.h:305
souffle::detail::joined_sequence::end
Iter end
The end of the range to be printed.
Definition: StreamUtil.h:84
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
std
Definition: Brie.h:3053
std::operator<<
ostream & operator<<(ostream &out, const array< T, E > &v)
Enables the generic printing of arrays assuming their element types are printable.
Definition: StreamUtil.h:233
souffle::stream_write_qualified_char_as_number::operator<<
std::ostream & operator<<(std::ostream &os, signed char c)
Definition: StreamUtil.h:59
souffle
Definition: AggregateOp.h:25
souffle::detail::joined_sequence::operator<<
friend std::ostream & operator<<(std::ostream &out, const joined_sequence &s)
The actual print method.
Definition: StreamUtil.h:98
souffle::detail::multiplying_printer::operator<<
friend std::ostream & operator<<(std::ostream &out, const multiplying_printer &printer)
Definition: StreamUtil.h:309
souffle::deref
A functor dereferencing a given type.
Definition: StreamUtil.h:151
p
a horizontalBars(j=m=void 0===a.axisX.type?new c.AutoScaleAxis(c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})):a.axisX.type.call(c, c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})), l=n=void 0===a.axisY.type?new c.StepAxis(c.Axis.units.y, b.normalized.series, o,{ticks:k}):a.axisY.type.call(c, c.Axis.units.y, b.normalized.series, o, a.axisY)) var p
Definition: htmlJsChartistMin.h:15
souffle::id::operator()
T & operator()(T &t) const
Definition: StreamUtil.h:137