DumperBase.h
Go to the documentation of this file.
1 /**
2  * @file lardataalg/Dumpers/DumperBase.h
3  * @brief Helper base class for implementing data product dump algorithms.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date March 8th, 2017
6  *
7  * Currently this is a header-only library.
8  *
9  */
10 
11 #ifndef LARDATAALG_DUMPERS_DUMPERBASE_H
12 #define LARDATAALG_DUMPERS_DUMPERBASE_H
13 
14 
15 // LArSoft includes
16 #include "lardataalg/Utilities/StatCollector.h" // lar::util::MinMaxCollector
18 
19 // C//C++ standard libraries
20 #include <string>
21 #include <vector>
22 #include <algorithm> // std::min()
23 #include <ios> // std::fixed
24 #include <iomanip> // std::setprecision(), std::setw()
25 #include <utility> // std::forward(), std::swap(), std::move()
26 #include <cassert>
27 
28 
29 /// Collection of utilities for dumping data on screen.
30 namespace dump {
31 
32  /**
33  * @brief Base class for data dumpers.
34  *
35  * This class provides some basic and common infrastructure:
36  * * managing of indentation strings
37  *
38  */
39  class DumperBase {
40 
41  struct IndentSettings {
42  std::string indent = ""; ///< Default indentation string.
43  std::string firstIndent = ""; ///< Indentation string for the first line.
44 
45  void set(std::string const& newIndent, std::string const& newFirstIndent)
46  { indent = newIndent; firstIndent = newFirstIndent; }
47  void set(std::string&& newIndent, std::string&& newFirstIndent)
48  {
49  indent = std::move(newIndent);
50  firstIndent = std::move(newFirstIndent);
51  }
52  void set(std::string const& newIndent) { set(newIndent, newIndent); }
53 
54  }; // struct IndentSettings
55 
56  std::vector<IndentSettings> fIndentSettings; ///< All indentation settings.
57 
58  public:
59 
60  /// Default constructor: no indentation.
61  DumperBase(): fIndentSettings{ {} } {}
62 
63  /**
64  * @brief Constructor: sets indentation.
65  * @param indent indentation for all lines except the first one
66  * (see `indent()`)
67  * @param firstIndent indentation for the first line (see `firstIndent()`)
68  */
70  : fIndentSettings{ { indent, firstIndent } }
71  {}
72 
73  /**
74  * @brief Constructor: sets indentation.
75  * @param indent indentation for all lines
76  */
77  DumperBase(std::string const& indent): DumperBase(indent, indent) {}
78 
79 
80  /**
81  * @name Indentation.
82  *
83  * Indentation strings are expected to be written by the dumping algorithms
84  * at the beginning of each output line to ensure the proper alignment of
85  * the dump. The `indent()` string should be written at the beginning of
86  * every new output line, with the exception of the first one, for which
87  * `firstIndent()` should be written instead.
88  *
89  * Note that this infrastructure only keeps track of the strings needed to
90  * indent the output, but it does not provide any tool to apply the
91  * indentation.
92  */
93  /// @{
94 
95  /// Returns the indentation string currently configured for all lines.
96  std::string const& indent() const { return indentSettings().indent; }
97 
98  /// Returns the indentation string currently configured for the first line.
99  std::string const& firstIndent() const
100  { return indentSettings().firstIndent; }
101 
102  /// Sets indentation strings to the specified values.
104  { indentSettings() = { indent, firstIndent }; }
105 
106  /// Sets both indentation strings to the same specified value.
107  void setIndent(std::string const& indent) { setIndent(indent, indent); }
108 
109 
110  /// Writes the indentation into a stream, and returns it for further output.
111  template <typename Stream>
112  Stream& indented(Stream&& out, bool first = false) const
113  { out << (first? firstIndent(): indent()); return out; }
114 
115  /// Writes first line indentation into a stream, and returns it for further
116  /// output.
117  template <typename Stream>
118  Stream& firstIndented(Stream&& out) const
119  { return indented(std::forward<Stream>(out), true); }
120 
121  /// Initiates a new output line, including indentation, and returns the
122  /// stream for further output.
123  template <typename Stream>
124  Stream& newline(Stream&& out) const
125  { return indented(std::forward<Stream>(out)); }
126 
127  /// @}
128 
129 
130  /**
131  * @brief Helper class to keep track of indenting.
132  * @tparam Stream type of output stream the class is using
133  *
134  * This class is single use, tied to a dumper and to a stream instance.
135  * It does not attempt to keep track of whether the output line is the
136  * first or not, and it does not try to detect end-of-line characters
137  * in the passed strings to insert internal indentation.
138  *
139  * Each object is tied to a `dump::DumperBase` object and it reflects its
140  * indentation settings, i.e. if indentation settings of the
141  * `dump::DumperBase` object are changed, the tied `Indenter` object will
142  * reflect the new settings.
143  *
144  * Example of usage:
145  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
146  * void dump(dump::DumperBase::Indenter<std::ostream>& out) {
147  *
148  * out.start() << "Here is the list of things to do:"; // first line
149  *
150  * out.newline() << " (1) first thing";
151  * out.newline() << " (2) third thing";
152  * out.newline() << " (3) fourth thing"
153  * << "\n" << out.indentString() << " (if allowed)";
154  * out << std::endl;
155  *
156  * }
157  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158  * Note how the manual indentation is more complicate than the "implicit"
159  * one.
160  */
161  template <typename Stream>
162  class Indenter {
163  Stream out;
165 
166  public:
167  using indenter_t = Indenter<Stream>; ///< This type.
168 
169  /// Records the underlying stream and the dumper associated.
170  Indenter(Stream out, DumperBase const& dumper)
171  : out(std::forward<Stream>(out)), dumper(dumper) {}
172 
173  /// Returns the default indentation string.
174  std::string const& indentString() const { return dumper.indent(); }
175 
176  /// Returns the indentation string for the first line.
178  { return dumper.firstIndent(); }
179 
180  /// Forwards data to the underlying stream.
181  template <typename T>
183  { out << std::forward<T>(v); return *this; }
184 
185  /// Inserts an indentation and returns the indenter for further output.
186  indenter_t& indent(bool first = false)
187  { dumper.indented(out, first); return *this; }
188 
189  /// Breaks the current line and returns the indenter for further output.
190  indenter_t& newline() { out << '\n'; return indent(); }
191 
192  /// Inserts a first-line indentation and returns the indenter for further
193  /// output.
194  indenter_t& start() { return indent(true); }
195 
196 
197  }; // Indenter<>
198 
199 
200  /// Returns an `Indenter` object tied to this dumper and `out` stream.
201  template <typename Stream>
202  decltype(auto) indenter(Stream&& out) const
203  { return Indenter<Stream>(std::forward<Stream>(out), *this); }
204 
205  protected:
206 
207  IndentSettings& indentSettings() { return fIndentSettings.back(); }
209  { return fIndentSettings.back(); }
210 
211  /// Stacks a copy of the current settings, and returns the "new" ones.
213  {
214  auto oldSettings = indentSettings();
215  fIndentSettings.push_back(std::move(oldSettings));
216  return indentSettings();
217  }
218 
219  /// Restores and returns the last saved settings.
221  {
222  if (fIndentSettings.size() > 1U) fIndentSettings.pop_back();
223  assert(!fIndentSettings.empty());
224  return indentSettings();
225  }
226 
227  }; // DumperBase
228 
229 
230  /// Changes the indentation settings of a dumper class and returns it back.
231  template <typename Dumper>
232  auto withIndentation
233  (Dumper&& dumper, std::string const& indent, std::string const& firstIndent)
234  { dumper.setIndent(indent, firstIndent); return dumper; }
235 
236  /// Changes the indentation settings of a dumper class and returns it back.
237  template <typename Dumper>
238  auto withIndentation
239  (Dumper&& dumper, std::string const& indent)
240  { return withIndentation(std::forward<Dumper>(dumper), indent, indent); }
241 
242 } // namespace dump
243 
244 
245 //----------------------------------------------------------------------------
246 
247 
248 #endif // LARDATAALG_DUMPERS_DUMPERBASE_H
std::string const & indentString() const
Returns the default indentation string.
Definition: DumperBase.h:174
DumperBase(std::string const &indent, std::string const &firstIndent)
Constructor: sets indentation.
Definition: DumperBase.h:69
void setIndent(std::string const &indent, std::string const &firstIndent)
Sets indentation strings to the specified values.
Definition: DumperBase.h:103
Stream & newline(Stream &&out) const
Definition: DumperBase.h:124
Stream & firstIndented(Stream &&out) const
Definition: DumperBase.h:118
std::string string
Definition: nybbler.cc:12
Helper class to keep track of indenting.
Definition: DumperBase.h:162
IndentSettings & restoreIndentSettings()
Restores and returns the last saved settings.
Definition: DumperBase.h:220
DumperBase(std::string const &indent)
Constructor: sets indentation.
Definition: DumperBase.h:77
STL namespace.
void setIndent(std::string const &indent)
Sets both indentation strings to the same specified value.
Definition: DumperBase.h:107
indenter_t & indent(bool first=false)
Inserts an indentation and returns the indenter for further output.
Definition: DumperBase.h:186
Classes gathering simple statistics.
indenter_t & newline()
Breaks the current line and returns the indenter for further output.
Definition: DumperBase.h:190
std::string const & firstIndent() const
Returns the indentation string currently configured for the first line.
Definition: DumperBase.h:99
auto withIndentation(Dumper &&dumper, std::string const &indent, std::string const &firstIndent)
Changes the indentation settings of a dumper class and returns it back.
Definition: DumperBase.h:233
DumperBase const & dumper
Definition: DumperBase.h:164
def move(depos, offset)
Definition: depos.py:107
IndentSettings & indentSettings()
Definition: DumperBase.h:207
std::string const & indent() const
Returns the indentation string currently configured for all lines.
Definition: DumperBase.h:96
std::string const & firstIndentString() const
Returns the indentation string for the first line.
Definition: DumperBase.h:177
decltype(auto) indenter(Stream &&out) const
Returns an Indenter object tied to this dumper and out stream.
Definition: DumperBase.h:202
std::string firstIndent
Indentation string for the first line.
Definition: DumperBase.h:43
std::ostream & operator<<(std::ostream &os, Analyzer::Table< T > const &t)
Definition: Analyzer.h:136
Stream & indented(Stream &&out, bool first=false) const
Writes the indentation into a stream, and returns it for further output.
Definition: DumperBase.h:112
Collection of utilities for dumping data on screen.
Definition: DumperBase.h:30
Indenter(Stream out, DumperBase const &dumper)
Records the underlying stream and the dumper associated.
Definition: DumperBase.h:170
IndentSettings & saveIndentSettings()
Stacks a copy of the current settings, and returns the "new" ones.
Definition: DumperBase.h:212
DumperBase()
Default constructor: no indentation.
Definition: DumperBase.h:61
std::string indent
Default indentation string.
Definition: DumperBase.h:42
IndentSettings const & indentSettings() const
Definition: DumperBase.h:208
Base class for data dumpers.
Definition: DumperBase.h:39
std::vector< IndentSettings > fIndentSettings
All indentation settings.
Definition: DumperBase.h:56