DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
toolbox.hxx
Go to the documentation of this file.
1#ifndef TIMING_INCLUDE_TIMING_TOOLBOX_HXX_
2#define TIMING_INCLUDE_TIMING_TOOLBOX_HXX_
3
4#include <boost/lexical_cast.hpp>
5
6namespace dunedaq::timing {
7
8//-----------------------------------------------------------------------------
9template<typename T>
10struct stoul
11{
12 BOOST_STATIC_ASSERT((boost::is_unsigned<T>::value));
14
15 operator T() const { return value; }
16
17 friend std::istream& operator>>(std::istream& in, stoul& out)
18 {
19 std::string buf;
20 in >> buf;
21 out.value = strtoul(buf.c_str(), NULL, 0);
22 return in;
23 }
24};
25//-----------------------------------------------------------------------------
26
27//-----------------------------------------------------------------------------
28template<typename T>
29struct stol
30{
31 BOOST_STATIC_ASSERT((boost::is_signed<T>::value));
33
34 operator T() const { return value; }
35
36 friend std::istream& operator>>(std::istream& in, stol& out)
37 {
38 std::string buf;
39 in >> buf;
40 out.value = strtol(buf.c_str(), NULL, 0);
41 return in;
42 }
43};
44//-----------------------------------------------------------------------------
45
46//-----------------------------------------------------------------------------
47template<typename T>
48std::string
49to_string(const T& v)
50{
51 return boost::lexical_cast<std::string>(v);
52}
53//-----------------------------------------------------------------------------
54
55//-----------------------------------------------------------------------------
56template<typename M>
57bool
58map_value_comparator(typename M::value_type& p1, typename M::value_type& p2)
59{
60 return p1.second < p2.second;
61}
62//-----------------------------------------------------------------------------
63
64//-----------------------------------------------------------------------------
65template<typename T>
66std::vector<T>
67sanitize(const std::vector<T>& vec)
68{
69 // Sanitise the inputs, by copying
70 std::vector<uint32_t> sorted(vec);
71
72 // ...sorting...
73 std::sort(sorted.begin(), sorted.end());
74
75 // and delete the duplicates (erase+unique require a sorted vector to delete duplicates)
76 sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end());
77
78 return sorted;
79}
80//-----------------------------------------------------------------------------
81
82//-----------------------------------------------------------------------------
83template<typename T, typename U>
84T
85safe_enum_cast(const U& value, const std::vector<T>& valid, const T& def)
86{
87 typename std::vector<T>::const_iterator it = std::find(valid.begin(), valid.end(), static_cast<T>(value));
88 return (it != valid.end() ? *it : def);
89}
90//-----------------------------------------------------------------------------
91
92//-----------------------------------------------------------------------------
93template<typename C>
94std::string
95join(const C& strings, const std::string& delimiter)
96{
97
98 if (strings.empty())
99 return "";
100
101 std::ostringstream string_stream;
102
103 string_stream << *strings.begin();
104
105 for (auto str_iter = std::next(strings.begin()); str_iter != strings.end(); ++str_iter) {
106 string_stream << delimiter;
107 string_stream << *str_iter;
108 }
109
110 return string_stream.str();
111}
112//-----------------------------------------------------------------------------
113
114//-----------------------------------------------------------------------------
115template<class T>
116std::string
117format_reg_value(T reg_value, uint32_t base)
118{
119 std::stringstream value_stream;
120 if (base == 16) {
121 value_stream << "0x" << std::hex;
122 } else if (base == 10) {
123 value_stream << std::dec;
124 } else {
125 // TODO warning?
126 TLOG() << "Unsupported number base: " << base;
127 value_stream << std::dec;
128 }
129 value_stream << reg_value;
130 return value_stream.str();
131}
132//-----------------------------------------------------------------------------
133
134//-----------------------------------------------------------------------------
135template<>
136inline std::string
137format_reg_value(std::string reg_value, uint32_t /*base*/)
138{
139 return reg_value;
140}
141//-----------------------------------------------------------------------------
142
143//-----------------------------------------------------------------------------
144template<>
145inline std::string
146format_reg_value(uhal::ValWord<uint32_t> reg_value, uint32_t base)
147{
148 std::stringstream value_stream;
149 if (base == 16) {
150 value_stream << "0x" << std::hex;
151 } else if (base == 10) {
152 value_stream << std::dec;
153 } else {
154 // TODO warning?
155 TLOG() << "format_reg_value: unsupported number base: " << base;
156 value_stream << std::dec;
157 }
158 value_stream << reg_value.value();
159 return value_stream.str();
160}
161//-----------------------------------------------------------------------------
162
163//-----------------------------------------------------------------------------
164template<class T>
165std::string
166format_reg_table(T data, std::string title, std::vector<std::string> headers)
167{
168
169 uint32_t table_width = 7;
170 uint32_t reg_column_width = 0;
171 uint32_t val_column_width = 3;
172 std::stringstream table_stream;
173
174 for (auto it = data.begin(); it != data.end(); ++it) {
175 reg_column_width = reg_column_width > it->first.size() ? reg_column_width : it->first.size();
176 val_column_width =
177 val_column_width > format_reg_value(it->second).size() ? val_column_width : format_reg_value(it->second).size();
178 }
179
180 // header vector length check
181 reg_column_width = reg_column_width > headers.at(0).size() ? reg_column_width : headers.at(0).size();
182 val_column_width = val_column_width > headers.at(1).size() ? val_column_width : headers.at(1).size();
183
184 table_width = table_width + reg_column_width + val_column_width;
185
186 if (title.size())
187 table_stream << boost::format("%=s\n") % boost::io::group(std::setw(table_width), std::setfill('-'), title);
188
189 if (headers.at(0).size() || headers.at(1).size()) {
190 table_stream << boost::format("+-%=s-+-%=s-+\n") %
191 boost::io::group(std::setw(reg_column_width), std::setfill('-'), "") %
192 boost::io::group(std::setw(val_column_width), std::setfill('-'), "");
193 table_stream << boost::format("| %=s | %=s |\n") % boost::io::group(std::setw(reg_column_width), headers.at(0)) %
194 boost::io::group(std::setw(val_column_width), headers.at(1));
195 }
196
197 table_stream << boost::format("+-%=s-+-%=s-+\n") %
198 boost::io::group(std::setw(reg_column_width), std::setfill('-'), "") %
199 boost::io::group(std::setw(val_column_width), std::setfill('-'), "");
200
201 for (auto it = data.begin(); it != data.end(); ++it) {
202 table_stream << boost::format("| %=s | %=s |\n") % boost::io::group(std::setw(reg_column_width), it->first) %
203 boost::io::group(std::setw(val_column_width), format_reg_value(it->second));
204 }
205 table_stream << boost::format("+-%=s-+-%=s-+\n") %
206 boost::io::group(std::setw(reg_column_width), std::setfill('-'), "") %
207 boost::io::group(std::setw(val_column_width), std::setfill('-'), "");
208
209 return table_stream.str();
210}
211//-----------------------------------------------------------------------------
212
213//-----------------------------------------------------------------------------
214template<class T>
215std::string
216format_counters_table(std::vector<T> counter_nodes,
217 std::vector<std::string> counter_node_titles,
218 std::string table_title,
219 std::vector<std::string> counter_labels,
220 std::string counter_labels_header)
221{
222
223 uint32_t counter_nodes_number = counter_nodes.size();
224 uint32_t table_width = 4 + (counter_nodes_number * 3);
225
226 std::vector<std::string> counter_node_titles_to_use;
227
228 if (!counter_node_titles.size()) {
229 for (uint32_t i = 0; i < counter_nodes.size(); ++i) {
230 counter_node_titles_to_use.push_back("Counters");
231 }
232 } else if (counter_nodes.size() != counter_node_titles.size()) {
233 throw FormatCountersTableNodesTitlesMismatch(ERS_HERE);
234 } else {
235 counter_node_titles_to_use = counter_node_titles;
236 }
237
238 uint32_t counter_number;
239 uint32_t counter_label_column_width = 0;
240
241 std::stringstream table_stream;
242 counter_number = counter_labels.size();
243
244 for (auto it = counter_labels.begin(); it != counter_labels.end(); ++it) {
245 counter_label_column_width = counter_label_column_width > it->size() ? counter_label_column_width : it->size();
246 }
247 counter_label_column_width =
248 counter_label_column_width > counter_labels_header.size() ? counter_label_column_width : counter_labels_header.size();
249
250 typedef std::vector<std::pair<std::string, std::string>> CounterValuesContainer;
251
252 std::vector<CounterValuesContainer> counter_value_containers;
253 std::vector<std::pair<uint32_t, uint32_t>> counter_value_column_widths;
254
255 for (auto node_iter = counter_nodes.begin(); node_iter != counter_nodes.end(); ++node_iter) {
256
257 CounterValuesContainer counter_values;
258
259 uint32_t counter_value_dec_column_width = 5;
260 uint32_t counter_value_hex_column_width = 5;
261
262 for (auto counter_iter = node_iter->begin(); counter_iter != node_iter->end(); ++counter_iter) {
263
264 std::string counter_value_dec = format_reg_value(*counter_iter, 10);
265 std::string counter_value_hex = format_reg_value(*counter_iter, 16);
266
267 counter_value_dec_column_width =
268 counter_value_dec_column_width > counter_value_dec.size() ? counter_value_dec_column_width : counter_value_dec.size();
269 counter_value_hex_column_width =
270 counter_value_hex_column_width > counter_value_hex.size() ? counter_value_hex_column_width : counter_value_hex.size();
271
272 counter_values.push_back(std::make_pair(counter_value_dec, counter_value_hex));
273 }
274
275 counter_value_containers.push_back(counter_values);
276 counter_value_column_widths.push_back(std::make_pair(counter_value_dec_column_width, counter_value_hex_column_width));
277 }
278
279 std::vector<uint32_t> counter_node_title_sizes;
280 // titles and border
281 std::stringstream counter_titles_row;
282 counter_titles_row << boost::format("| %=s |") % boost::io::group(std::setw(counter_label_column_width), "");
283 table_width = table_width + counter_label_column_width;
284 for (uint32_t i = 0; i < counter_nodes_number; ++i) {
285 uint32_t dec_width = counter_value_column_widths.at(i).first;
286 uint32_t hex_width = counter_value_column_widths.at(i).second;
287
288 uint32_t counter_title_size = counter_node_titles_to_use.at(i).size();
289
290 if (counter_title_size > (dec_width + hex_width + 3)) {
291
292 if ((counter_title_size - 3) % 2)
293 ++counter_title_size;
294
295 counter_value_column_widths.at(i).first = (counter_title_size - 3) / 2;
296 counter_value_column_widths.at(i).second = (counter_title_size - 3) / 2;
297
298 } else {
299 counter_title_size = (dec_width + hex_width + 3);
300 }
301 counter_titles_row << boost::format(" %=s |") %
302 boost::io::group(std::setw(counter_title_size), counter_node_titles_to_use.at(i));
303 counter_node_title_sizes.push_back(counter_title_size);
304 table_width = table_width + counter_title_size;
305 }
306 counter_titles_row << std::endl;
307
308 std::stringstream title_row_border;
309 title_row_border << boost::format("+-%=s-+") %
310 boost::io::group(std::setw(counter_label_column_width), std::setfill('-'), "");
311 for (uint32_t i = 0; i < counter_nodes_number; ++i) {
312 title_row_border << boost::format("-%=s-+") %
313 boost::io::group(std::setw(counter_node_title_sizes.at(i)), std::setfill('-'), "");
314 }
315 title_row_border << std::endl;
316
317 if (table_title.size())
318 table_stream << boost::format("%=s\n") % boost::io::group(std::setw(table_width), std::setfill('-'), table_title);
319
320 table_stream << title_row_border.str();
321 table_stream << counter_titles_row.str();
322 table_stream << title_row_border.str();
323 //
324
325 // headers
326 std::stringstream counter_headers;
327 counter_headers << boost::format("| %=s |") %
328 boost::io::group(std::setw(counter_label_column_width), counter_labels_header);
329 for (uint32_t j = 0; j < counter_nodes_number; ++j) {
330 uint32_t dec_width = counter_value_column_widths.at(j).first;
331 uint32_t hex_width = counter_value_column_widths.at(j).second;
332 counter_headers << boost::format(" %=s | %=s |") % boost::io::group(std::setw(dec_width), "cnts") %
333 boost::io::group(std::setw(hex_width), "hex");
334 }
335 table_stream << counter_headers.str() << std::endl;
336 //
337
338 // top counter row border
339 std::stringstream row_border;
340 row_border << boost::format("+-%=s-+") % boost::io::group(std::setw(counter_label_column_width), std::setfill('-'), "");
341 for (uint32_t j = 0; j < counter_nodes_number; ++j) {
342 uint32_t dec_width = counter_value_column_widths.at(j).first;
343 uint32_t hex_width = counter_value_column_widths.at(j).second;
344 row_border << boost::format("-%=s-+-%=s-+") % boost::io::group(std::setw(dec_width), std::setfill('-'), "") %
345 boost::io::group(std::setw(hex_width), std::setfill('-'), "");
346 }
347 row_border << std::endl;
348 table_stream << row_border.str();
349 //
350
351 // counter rows
352 for (uint32_t i = 0; i < counter_number; ++i) {
353 std::stringstream table_row_stream;
354
355 table_row_stream << boost::format("| %=s |") %
356 boost::io::group(std::setw(counter_label_column_width), counter_labels.at(i));
357
358 for (uint32_t j = 0; j < counter_nodes_number; ++j) {
359 uint32_t dec_width = counter_value_column_widths.at(j).first;
360 uint32_t hex_width = counter_value_column_widths.at(j).second;
361
362 std::string dec_value = counter_value_containers.at(j).at(i).first;
363 std::string hex_value = counter_value_containers.at(j).at(i).second;
364
365 table_row_stream << boost::format(" %=s | %=s |") % boost::io::group(std::setw(dec_width), dec_value) %
366 boost::io::group(std::setw(hex_width), hex_value);
367 }
368 table_stream << table_row_stream.str() << std::endl;
369 }
370 //
371
372 // bottom counter row border
373 table_stream << row_border.str();
374
375 return table_stream.str();
376}
377//-----------------------------------------------------------------------------
378
379//-----------------------------------------------------------------------------
380template<typename T>
381std::string
382vec_fmt(const std::vector<T>& vec)
383{
384 std::ostringstream oss;
385 oss << "[";
386
387 for (typename std::vector<T>::const_iterator it = vec.begin(); it != vec.end(); it++)
388 oss << *it << ",";
389 oss.seekp(oss.tellp() - 1l);
390 oss << "]";
391
392 return oss.str();
393}
394//-----------------------------------------------------------------------------
395
396//-----------------------------------------------------------------------------
397template<typename T>
398std::string
399short_vec_fmt(const std::vector<T>& vec)
400{
401 if (vec.size() == 0)
402 return "[]";
403 else if (vec.size() == 1)
404 return "[" + boost::lexical_cast<std::string>(vec.at(0)) + "]";
405
406 std::ostringstream oss;
407 oss << "[";
408
409 // Initial search range
410 T first = vec.at(0);
411 T last = first;
412 for (typename std::vector<T>::const_iterator it = vec.begin() + 1; it != vec.end(); it++) {
413 // if *it is contiguous to last, carry on searching
414 if ((*it) == (last + 1)) {
415 last = *it;
416 continue;
417 }
418
419 if (first == last)
420 // if first and last are the same, this is an isolated number
421 oss << first << ",";
422 else
423 // otherwise it's a range
424 oss << first << "-" << last << ",";
425
426 // *it is the first value of the new range
427 first = *it;
428 last = *it;
429 }
430
431 // Process the last range
432 if (first == last)
433 oss << first << ",";
434 else
435 oss << first << "-" << last << ",";
436
437 // Is this actually necessary?
438 // Replace final "," with a "]"
439 oss.seekp(oss.tellp() - 1l);
440 oss << "]";
441
442 return oss.str();
443}
444//-----------------------------------------------------------------------------
445} // namespace dunedaq::timing
446
447#endif // TIMING_INCLUDE_TIMING_TOOLBOX_HXX_
#define ERS_HERE
#define TLOG(...)
Definition macro.hpp:22
< Message parameters
bool map_value_comparator(typename M::value_type &p1, typename M::value_type &p2)
Definition toolbox.hxx:58
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
Definition toolbox.hxx:166
std::string vec_fmt(const std::vector< T > &vec)
Definition toolbox.hxx:382
std::vector< T > sanitize(const std::vector< T > &vec)
Definition toolbox.hxx:67
std::string to_string(const T &v)
Definition toolbox.hxx:49
std::string format_counters_table(std::vector< T > counter_nodes, std::vector< std::string > counter_node_titles, std::string table_title, std::vector< std::string > counter_labels, std::string counter_labels_header)
Format reg-value table.
Definition toolbox.hxx:216
std::string join(const C &strings, const std::string &delimiter)
Converts a vector of strings in a delimiter-separated string.
Definition toolbox.hxx:95
T safe_enum_cast(const U &value, const std::vector< T > &valid, const T &def)
Definition toolbox.hxx:85
std::string short_vec_fmt(const std::vector< T > &vec)
Definition toolbox.hxx:399
std::string format_reg_value(T reg_value, uint32_t base)
Definition toolbox.hxx:117
FELIX Initialization std::string initerror FELIX queue timed out
friend std::istream & operator>>(std::istream &in, stol &out)
Definition toolbox.hxx:36
BOOST_STATIC_ASSERT((boost::is_signed< T >::value))
friend std::istream & operator>>(std::istream &in, stoul &out)
Definition toolbox.hxx:17
BOOST_STATIC_ASSERT((boost::is_unsigned< T >::value))