DumpUtils.h
Go to the documentation of this file.
1 /**
2  * @file DumpUtils.h
3  * @brief Utilities to dump objects into a stream.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date February 28, 2017
6  *
7  * The library `DumpUtils.h` is currently header-only.
8  *
9  */
10 
11 #ifndef GARSOFT_COREUTILS_DUMPUTILS_H
12 #define GARSOFT_COREUTILS_DUMPUTILS_H
13 
14 // C++ libraries
15 #include <string>
16 #include <sstream>
17 #include <type_traits>
18 
19 
20 namespace gar {
21 
22 
23  /// Namespace for GArSoft dumping utilities.
24  namespace dump {
25 
26  namespace details {
27 
28  template <typename Coll>
29  auto ptr_cbegin(Coll const& v) { using std::cbegin; return cbegin(v); }
30 
31  template <typename T>
32  std::add_const_t<T>* ptr_cbegin(T* ptr) { return ptr; }
33 
34 
35  /// Inserts `n` of elements of `a` in the specified stream.
36  template <typename Stream, typename Array>
37  void dumpArray(Stream&& out, Array&& a, size_t n) {
38  out << "{";
39  if (n == 0) { out << "}"; return; }
40  auto it = ptr_cbegin(a);
41  out << " " << *it;
42  std::size_t i = 0;
43  while (++i < n) out << "; " << (*++it);
44  out << " }";
45  } // dumpArray()
46 
47  } // namespace details
48 
49  /**
50  * @brief Dumps the first N elements of an array.
51  * @tparam Array the array type (supporting indexing operator)
52  *
53  * The dump is producer by the call operator, in the form
54  *
55  * { a1, a2, ... aN }
56  *
57  *
58  */
59  template <typename Array>
60  struct ArrayDumper {
61  using Array_t = Array;
63 
64  Array_t const& a; ///< A reference to the array to be printed.
65  size_t n; ///< Number of elements to be printed.
66 
67  ArrayDumper(Array_t const& aloc, size_t nloc): a(aloc), n(nloc) {}
68 
69  // constructors ahead
70  ArrayDumper(This_t const& from) = default;
71  ArrayDumper(This_t&& from) = default;
72  ArrayDumper& operator=(This_t const& from) = delete;
73  ArrayDumper& operator=(This_t&& from) = delete;
74 
75  /// Inserts the content of the referenced array into the specified stream.
76  template <typename Stream>
77  void operator() (Stream&& out) const
78  { details::dumpArray(std::forward<Stream>(out), a, n); }
79 
80  /// Converts the content of the stored vector into a string.
81  explicit operator std::string() const
82  { std::ostringstream sstr; this->operator()(sstr); return sstr.str(); }
83 
84  }; // struct ArrayDumper
85 
86 
87  template <typename T>
88  struct ArrayDumper<T*> {
89  using Array_t = T*;
91 
92  Array_t a; ///< A reference to the array to be printed.
93  size_t n; ///< Number of elements to be printed.
94 
95  ArrayDumper(Array_t aloc, size_t nloc): a(aloc), n(nloc) {}
96 
97  /// Inserts the content of the referenced array into the specified stream.
98  template <typename Stream>
99  void operator() (Stream&& out) const
100  { details::dumpArray(std::forward<Stream>(out), a, n); }
101 
102  /// Converts the content of the stored vector into a string.
103  explicit operator std::string() const
104  { std::ostringstream sstr; this->operator()(sstr); return sstr.str(); }
105 
106  }; // struct ArrayDumper<T*>
107 
108 
109  /**
110  * @brief Manipulator managing the dump of the vector content into a stream.
111  * @tparam Vector the type of vector to be dumped
112  *
113  * The manipulator is constructed with the object that needs to be dumped.
114  * This implementation requires a vector of at least 3D with methods `X()`,
115  * `Y()` and `Z()`.
116  * The dump is producer by the call operator, in the form
117  *
118  * { vx, vy, vz }
119  *
120  *
121  * An overloaded insertion operator will call the `operator()` method of
122  * the manipulator to perform the insertion.
123  *
124  * This class can be specialised to manage different vector types.
125  * For example:
126  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
127  * #include <array>
128  *
129  * namespace gar {
130  * namespace dump {
131  *
132  * // specialization for 3D std::array<>
133  * template <typename T>
134  * struct VectorDumper<std::array<T, 3U>> {
135  *
136  * using Vector_t = std::array<T, 3U>;
137  *
138  * Vector_t const& a;
139  *
140  * VectorDumper(Vector_t const& a): a(a) {}
141  *
142  * template <typename Stream>
143  * void operator() (Stream&& out) const
144  * { out << "{ " << a[0] << "; " << a[1] << "; " << a[2] << " }"; }
145  *
146  * }; // struct VectorDumper<array>
147  *
148  *
149  * } // namespace dump
150  * } // namespace gar
151  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
152  *
153  */
154  template <typename Vector>
155  struct VectorDumper {
156  using Vector_t = Vector;
158 
159  Vector_t const& v; ///< A reference to the vector to be printed.
160 
161  explicit VectorDumper(Vector_t const& vloc): v(vloc) {}
162 
163  // constructors ahead
164  VectorDumper(This_t const& from) = default;
165  VectorDumper(This_t&& from) = default;
166  VectorDumper& operator=(This_t const& from) = delete;
167  VectorDumper& operator=(This_t&& from) = delete;
168 
169  /// Inserts the content of the stored vector into the specified stream.
170  template <typename Stream>
171  void operator() (Stream&& out) const
172  { out << "{ " << v.X() << "; " << v.Y() << "; " << v.Z() << " }"; }
173 
174  /// Converts the content of the stored vector into a string.
175  explicit operator std::string() const
176  { std::ostringstream sstr; this->operator()(sstr); return sstr.str(); }
177 
178  }; // struct VectorDumper<>
179 
180 
181  // Specialization for bare pointers.
182  template <typename T>
184  explicit VectorDumper(T* v): ArrayDumper<T const*>(v, 3U) {}
185  }; // VectorDumper<T*>
186 
187  // Specialization for C-style arrays.
188  template <typename T>
189  struct VectorDumper<T[3]>: public ArrayDumper<T const*> {
190  explicit VectorDumper(T const* v): ArrayDumper<T const*>(v, 3U) {}
191  }; // VectorDumper<T*>
192 
193 
194 
195  /**
196  * @brief Returns a manipulator which will print the specified array.
197  * @tparam N the number of entries to be printed
198  * @tparam Array the type of array to be printed
199  * @param a the array to be printed
200  * @return a manipulator
201  *
202  * Example of usage:
203  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
204  * double const data[5] = { 1., 2., 3., 4., 6. };
205  * std::cout << "Data: " << gar::dump::array<5>(data) << std::endl;
206  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207  * will produce an output like:
208  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
209  * Data: { 1; 2; 3; 4; 6 }
210  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211  *
212  * Addition of specific classes can be achieved via specialization of
213  * the class `ArrayDumper`.
214  *
215  *
216  * Requirements
217  * -------------
218  *
219  * * the type `Array` is required to respond to a global function `cbegin()`
220  * (like `std::cbegin()`) with a forward iterator
221  * * the value type of the iterator returned by the aforementioned `Array`
222  * method must have its insertion operator into a stream defined
223  * * the array `a` must not fall out of scope until the insertion into
224  * the stream happens
225  *
226  */
227  template <size_t N, typename Array>
228  auto array(Array const& a) { return ArrayDumper<Array>(a, N); }
229 
230 
231  /**
232  * @brief Returns a manipulator which will print the specified array.
233  * @tparam Vector type of vector to be printed
234  * @param v the vector to be printed
235  * @return a manipulator
236  *
237  * Example of usage:
238  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
239  * std::vector<double> data = { 1., 2., 3., 4., 6. };
240  * std::cout << "Data: " << gar::dump::vector(data) << std::endl;
241  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242  * will produce an output like:
243  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
244  * Data: { 1; 2; 3; 4; 6 }
245  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246  *
247  * Addition of specific classes can be achieved via specialization of
248  * the class `ArrayDumper`.
249  *
250  *
251  * Requirements
252  * -------------
253  *
254  * * a method `Vector::size() const` must be available returning the number
255  * of elements in the vector
256  * * the type `Vector` is required to respond to a global function
257  * `cbegin()` (like `std::cbegin()`) with a forward iterator
258  * * the value type returned by the aforementioned `Vector` method must have
259  * its insertion operator into a stream defined
260  * * the vector `v` must not fall out of scope until the insertion into
261  * the stream happens
262  *
263  */
264  template <typename Vector>
265  auto vector(Vector const& v) { return ArrayDumper<Vector>(v, v.size()); }
266 
267 
268 
269  /**
270  * @brief Returns a manipulator which will print the specified vector.
271  * @tparam Vector3D the type of 3D vector to be printed
272  * @param v the vector to be printed
273  * @return a manipulator
274  *
275  * Example of usage:
276  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
277  * TVector3 pos;
278  * std::cout << "Position: " << gar::dump::vector3D(pos) << std::endl;
279  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280  * will produce an output like:
281  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282  * Position: { 0; 0; 0 }
283  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
284  *
285  * Addition of specific classes can be achieved via specialization of
286  * the class `VectorDumper`.
287  *
288  *
289  * Requirements
290  * -------------
291  *
292  * * the type `Vector3D` is required to provide constant accessor methods
293  * returning the vector components, called `X()`, `Y()` and `Z()`
294  * * the values returned by the aforementioned `Vector3D` methods must have
295  * their insertion operator into a stream defined
296  * * the vector `v` must not fall out of scope until the insertion into
297  * the stream happens
298  *
299  */
300  template <typename Vector3D>
301  auto vector3D(Vector3D const& v) { return VectorDumper<Vector3D>(v); }
302 
303 
304 
305  /**
306  * @brief Dumps the array contained in the manipulator into a stream.
307  * @tparam Stream the type of output stream
308  * @tparam Array the type of array to be printed
309  * @tparam NPrint the number of element of the array to be printed
310  * @param out the output stream
311  * @param manip the manipulator containing the array to be printed
312  * @return a reference to the output stream
313  * @see ArrayDumper
314  *
315  * Example of usage:
316  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
317  * double const data[5] = { 1., 2., 3., 4., 6. };
318  * std::cout << "Position: " << gar::dump::array<5>(data) << std::endl;
319  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
320  * will produce an output like:
321  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322  * Position: { 1, 2, 3, 4, 5 }
323  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
324  *
325  *
326  * Requirements
327  * -------------
328  *
329  * * the type `Vector3D` is required to provide constant accessor methods
330  * returning the vector components, called `X()`, `Y()` and `Z()`
331  * * the values returned by the aforementioned `Vector3D` methods must have
332  * their insertion operator into `Stream` defined
333  *
334  */
335  template <typename Stream, typename Array>
336  Stream& operator<< (Stream&& out, ArrayDumper<Array>&& manip)
337  { manip(std::forward<Stream>(out)); return out; }
338 
339 
340  /**
341  * @brief Dumps the vector contained in the manipulator into a stream.
342  * @tparam Stream the type of output stream
343  * @tparam Vector3D the type of 3D vector to be printed
344  * @param out the output stream
345  * @param manip the manipulator containing the vector to be printed
346  * @return a reference to the output stream
347  * @see VectorDumper
348  *
349  * Example of usage:
350  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
351  * TVector3 pos;
352  * std::cout << "Position: " << gar::dump::vector3D(pos) << std::endl;
353  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
354  * will produce an output like:
355  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
356  * Position: { 0; 0; 0 }
357  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
358  *
359  *
360  * Requirements
361  * -------------
362  *
363  * * the type `Vector3D` is required to provide constant accessor methods
364  * returning the vector components, called `X()`, `Y()` and `Z()`
365  * * the values returned by the aforementioned `Vector3D` methods must have
366  * their insertion operator into Stream defined
367  *
368  */
369  template <typename Stream, typename Vector>
370  Stream& operator<< (Stream&& out, VectorDumper<Vector>&& manip)
371  { manip(std::forward<Stream>(out)); return out; }
372 
373  /**
374  * @brief Concatenates a vector to the specified string.
375  * @tparam String a string type that can handle "addition" to `std::string`
376  * @tparam Vector3D the type of 3D vector to be printed
377  * @param s the string
378  * @param manip the manipulator containing the vector to be printed
379  * @return a new string with s concatenated to a rendering of the vector
380  * @see VectorDumper
381  *
382  * Example of usage:
383  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
384  * TVector3 pos;
385  * std::runtime_error e("Position: " + gar::dump::vector3D(pos));
386  * std::cout << e.what() << std::endl;
387  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
388  * will produce an output like:
389  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
390  * Position: { 0; 0; 0 }
391  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
392  *
393  *
394  * Requirements
395  * -------------
396  *
397  * * the type `Vector3D` is required to provide constant accessor methods
398  * returning the vector components, called `X()`, `Y()` and `Z()`
399  * * the values returned by the aforementioned `Vector3D` methods must have
400  * their insertion operator into Stream defined
401  *
402  */
403  template <typename String, typename Vector>
405  { return s + std::string(manip);}
406 
407  /// Creates a string with s concatenated to the rendered vector.
408  template <typename Vector>
409  std::string operator+ (const char* s, VectorDumper<Vector> const& manip)
410  { return std::string(s) + manip;}
411 
412  /// @see documentation of function with arguments swapped.
413  template <typename String, typename Vector>
415  { return std::string(manip) + s;}
416 
417  /// Creates a string with the rendered vector concatenated to s.
418  template <typename Vector>
419  std::string operator+ (VectorDumper<Vector> const& manip, const char* s)
420  { return manip + std::string(s);}
421 
422  /// Appends a string rendering of a vector to the specified string.
423  template <typename String, typename Vector>
425  { return s += std::string(manip); }
426 
427  } // namespace dump
428 
429 
430 } // namespace gar
431 
432 
433 #endif // GARSOFT_COREUTILS_DUMPUTILS_H
VectorDumper(Vector_t const &vloc)
Definition: DumpUtils.h:161
ArrayDumper(Array_t aloc, size_t nloc)
Definition: DumpUtils.h:95
vector< T > Vector
size_t n
Number of elements to be printed.
Definition: DumpUtils.h:93
std::string string
Definition: nybbler.cc:12
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
String & operator+=(String &s, VectorDumper< Vector > const &manip)
Appends a string rendering of a vector to the specified string.
Definition: DumpUtils.h:424
auto vector3D(Vector3D const &v)
Returns a manipulator which will print the specified vector.
Definition: DumpUtils.h:301
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:31
ArrayDumper(Array_t const &aloc, size_t nloc)
Definition: DumpUtils.h:67
#define Array
Definition: scanner.cpp:11549
void dumpArray(Stream &&out, Array &&a, size_t n)
Inserts n of elements of a in the specified stream.
Definition: DumpUtils.h:37
std::void_t< T > n
const double a
Dumps the first N elements of an array.
Definition: DumpUtils.h:60
size_t n
Number of elements to be printed.
Definition: DumpUtils.h:65
Array_t const & a
A reference to the array to be printed.
Definition: DumpUtils.h:64
Vector_t const & v
A reference to the vector to be printed.
Definition: DumpUtils.h:159
String operator+(String const &s, VectorDumper< Vector > const &manip)
Concatenates a vector to the specified string.
Definition: DumpUtils.h:404
Collection of utilities for dumping data on screen.
Definition: DumperBase.h:30
General GArSoft Utilities.
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:82
auto ptr_cbegin(Coll const &v)
Definition: DumpUtils.h:29
Manipulator managing the dump of the vector content into a stream.
Definition: DumpUtils.h:155
static QCString * s
Definition: config.cpp:1042
Array_t a
A reference to the array to be printed.
Definition: DumpUtils.h:92