timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
stream.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25/** \file data/stream.hpp
26 * \headerfile data/stream.hpp "timemory/data/stream.hpp"
27 * Provides a simple stream type that generates a vector of strings for column alignment
28 *
29 */
30
31#pragma once
32
37
38#include <algorithm>
39#include <cassert>
40#include <iomanip>
41#include <iostream>
42#include <map>
43#include <set>
44#include <string>
45#include <vector>
46
47namespace tim
48{
49namespace data
50{
51namespace base
52{
53//--------------------------------------------------------------------------------------//
54//
56{
58 using stringstream_t = std::stringstream;
59 using format_flags = std::ios_base::fmtflags;
60
61 explicit stream_entry(int _row = -1, int _col = -1, format_flags _fmt = {},
62 int _width = 0, int _prec = 0, bool _center = false)
63 : m_center(_center)
64 , m_row(_row)
65 , m_column(_col)
66 , m_width(_width)
67 , m_precision(_prec)
68 , m_format(_fmt)
69 {}
70
71 ~stream_entry() = default;
72 stream_entry(const stream_entry&) = default;
76
77 TIMEMORY_NODISCARD string_t get() const { return m_value; }
78
79 TIMEMORY_NODISCARD bool center() const { return m_center; }
80 TIMEMORY_NODISCARD bool left() const { return m_left; }
81 TIMEMORY_NODISCARD int row() const { return m_row; }
82 TIMEMORY_NODISCARD int width() const { return m_width; }
83 TIMEMORY_NODISCARD int column() const { return m_column; }
84 TIMEMORY_NODISCARD int precision() const { return m_precision; }
85 TIMEMORY_NODISCARD format_flags flags() const { return m_format; }
86
87 void center(bool v) { m_center = v; }
88 void left(bool v) { m_left = v; }
89 void row(int v) { m_row = v; }
90 void width(int v) { m_width = v; }
91 void column(int v) { m_column = v; }
92 void precision(int v) { m_precision = v; }
93 void setf(format_flags v) { m_format = v; }
94
95 void operator()(const string_t& val) { m_value = val; }
96
97 template <typename Tp>
98 void construct(const Tp& val)
99 {
101 ss.setf(m_format);
102 ss << std::setprecision(m_precision) << val;
103 m_value = ss.str();
104 if(settings::max_width() > 0 && m_value.length() > (size_t) settings::max_width())
105 {
106 //
107 // don't truncate and add ellipsis if max width is really small
108 //
109 if(settings::max_width() > 20)
110 {
111 m_value = m_value.substr(0, settings::max_width() - 3);
112 m_value += "...";
113 }
114 else
115 {
116 m_value = m_value.substr(0, settings::max_width());
117 }
118 }
119 }
120
121 friend bool operator<(const stream_entry& lhs, const stream_entry& rhs)
122 {
123 return (lhs.row() == rhs.row()) ? (lhs.column() < rhs.column())
124 : (lhs.row() < rhs.row());
125 }
126
127protected:
128 bool m_center = false;
129 bool m_left = false;
130 int m_row = 0;
131 int m_column = 0;
132 int m_width = 0;
133 int m_precision = 0;
136};
137
138//--------------------------------------------------------------------------------------//
139
140template <typename StreamT, typename Tp>
141static void
142write_entry(StreamT& ss, const Tp& obj)
143{
144 using stringstream_t = std::stringstream;
145
146 auto itr = obj.get();
147
148 if(obj.row() == 0 || obj.center())
149 {
150 int _w = obj.width();
151 int _i = itr.length();
152 int _whalf = _w / 2;
153 int _ihalf = (_i + 1) / 2;
154 int _wrem = (_whalf - _ihalf);
155 _wrem = std::max<int>(_wrem, 0);
156 if(_i + _wrem > _w - 3)
157 _wrem = _w - 3 - _i;
158 // e.g. 4 leading spaces, 2 spaces at end
159 if(((_wrem - itr.length()) - (_w - 2)) > 1)
160 _wrem -= 1;
161 stringstream_t ssbeg;
162 ssbeg << std::setw(_wrem) << "" << itr;
163 ss << std::left << std::setw(_w - 2) << ssbeg.str();
164 }
165 else
166 {
167 if(obj.column() == 0 || obj.left())
168 {
169 stringstream_t _ss;
170 _ss << std::left << itr;
171 int remain = obj.width() - _ss.str().length() - 2;
172 ss << _ss.str() << std::setw(remain) << "";
173 }
174 else
175 {
176 ss << std::right << std::setw(obj.width() - 2) << itr;
177 }
178 }
179}
180
181//--------------------------------------------------------------------------------------//
182
183} // namespace base
184
185//======================================================================================//
186
188{
189 header() = default;
190 ~header() = default;
191 header(const header&) = default;
192 header(header&&) = default;
193 header& operator=(const header&) = default;
194 header& operator=(header&&) = default;
195
196 explicit header(const std::string& _val, format_flags _fmt = {}, int _width = 0,
197 int _prec = 0, bool _center = true)
198 : base::stream_entry(0, -1, _fmt, _width, _prec, _center)
199 {
201 }
202
203 template <typename Tp>
204 explicit header(const Tp& _val, format_flags _fmt, int _width, int _prec,
205 bool _center = true)
206 : base::stream_entry(0, -1, _fmt, _width, _prec, _center)
207 {
208 base::stream_entry::construct(std::forward<Tp>(_val));
209 }
210};
211
212//--------------------------------------------------------------------------------------//
213
215{
216 template <typename Tp>
217 explicit entry(Tp&& _val, header& _hdr, bool _center = false, bool _left = false)
218 : base::stream_entry(_hdr)
219 , m_hdr(&_hdr)
220
221 {
222 m_center = _center;
223 m_left = _left;
224 base::stream_entry::construct(std::forward<Tp>(_val));
225 }
226
227 explicit entry(const std::string& _val, header& _hdr, bool _center = false,
228 bool _left = true)
229 : base::stream_entry(_hdr)
230 , m_hdr(&_hdr)
231 , m_permit_empty(true)
232 {
233 m_center = _center;
234 m_left = _left;
236 }
237
238 entry(const entry& _rhs)
239 : base::stream_entry(_rhs)
240 , m_hdr(_rhs.m_hdr)
241 {}
242
243 ~entry() = default;
244 entry(entry&&) = default;
245 entry& operator=(const entry&) = default;
246 entry& operator=(entry&&) = default;
247
248 TIMEMORY_NODISCARD bool permit_empty() const { return m_permit_empty; }
249 TIMEMORY_NODISCARD int width() const { return m_hdr->width(); }
250 TIMEMORY_NODISCARD int precision() const { return m_hdr->precision(); }
251 TIMEMORY_NODISCARD format_flags flags() const { return m_hdr->flags(); }
252
253 void permit_empty(bool v) { m_permit_empty = v; }
254 void width(int v) { m_hdr->width(v); }
255 void precision(int v) { m_hdr->precision(v); }
256 void setf(format_flags v) { m_hdr->setf(v); }
257
258 TIMEMORY_NODISCARD const header& get_header() const { return *m_hdr; }
259 header& get_header() { return *m_hdr; }
260
261private:
262 header* m_hdr = nullptr;
263 bool m_permit_empty = false;
264};
265
266//--------------------------------------------------------------------------------------//
267
268struct stream
269{
270 template <typename T>
271 using set_t = std::set<T>;
272
273 template <typename K, typename M>
274 using map_t = std::map<K, M>;
275
276 template <typename K, typename M>
277 using pair_t = std::pair<K, M>;
278
279 template <typename T>
280 using vector_t = std::vector<T>;
281
283 using stringstream_t = std::stringstream;
284 using format_flags = std::ios_base::fmtflags;
286
289
292
296
297public:
299
300public:
301 explicit stream(char _delim = '|', char _fill = '-', format_flags _fmt = {},
302 int _width = 0, int _prec = 0, bool _center = false)
303 : m_center(_center)
304 , m_fill(_fill)
305 , m_delim(_delim)
306 , m_width(_width)
307 , m_precision(_prec)
308 , m_format(_fmt)
309 {}
310
311 TIMEMORY_NODISCARD bool center() const { return m_center; }
312 TIMEMORY_NODISCARD int precision() const { return m_precision; }
313 TIMEMORY_NODISCARD int width() const { return m_width; }
314 TIMEMORY_NODISCARD char delim() const { return m_delim; }
315 TIMEMORY_NODISCARD format_flags flags() const { return m_format; }
316 TIMEMORY_NODISCARD int64_t freq() const { return m_separator_freq; }
317
318 void center(bool v) { m_center = v; }
319 void precision(int v) { m_precision = v; }
320 void width(int v) { m_width = v; }
321 void delim(char v) { m_delim = v; }
322 void setf(format_flags v) { m_format = v; }
323 void setfreq(int64_t v) { m_separator_freq = v; }
324
325 // NOLINTNEXTLINE
326 void set_name(string_t v) { m_name = v; }
327 // NOLINTNEXTLINE
328 void set_banner(string_t v) { m_banner = v; }
329
330 static int64_t index(const string_t& _val, const vector_t<string_t>& _obj)
331 {
332 for(size_t i = 0; i < _obj.size(); ++i)
333 {
334 if(_obj.at(i) == _val)
335 return static_cast<int64_t>(i);
336 }
337 return -1;
338 }
339
340 static int64_t insert(const string_t& _val, vector_t<string_t>& _obj)
341 {
342 auto idx = index(_val, _obj);
343 if(idx < 0)
344 {
345 idx = _obj.size();
346 _obj.push_back(_val);
347 if(settings::debug())
348 printf("> inserted '%s'...\n", _val.c_str());
349 }
350 return idx;
351 }
352
353 template <typename Tp>
354 static int64_t index(const string_t& _val,
355 const vector_t<pair_t<string_t, vector_t<Tp>>>& _obj)
356 {
357 for(size_t i = 0; i < _obj.size(); ++i)
358 {
359 if(_obj.at(i).first == _val)
360 return static_cast<int64_t>(i);
361 }
362 return -1;
363 }
364
365 template <typename Tp>
366 static int64_t insert(const string_t& _val,
368 {
369 auto idx = index(_val, _obj);
370 if(idx < 0)
371 {
372 idx = _obj.size();
373 _obj.resize(_obj.size() + 1);
374 _obj[idx].first = _val;
375 if(settings::debug())
376 printf("[%s]> inserted '%s'...\n", demangle<Tp>().c_str(), _val.c_str());
377 }
378 return idx;
379 }
380
381 void set_prefix_begin(int val = -1)
382 {
383 m_prefix_begin = (val < 0) ? ((int) m_order.size()) : val;
384 }
385
386 void set_prefix_end(int val = -1)
387 {
388 m_prefix_end = (val < 0) ? ((int) m_order.size()) : val;
389 }
390
391 void insert_break(int val = -1)
392 {
393 m_break.insert((val < 0) ? ((int) m_order.size()) : val);
394 }
395
397 {
398 if(_hdr.get().empty())
399 throw std::runtime_error("Header has no value");
400
401 auto _w = std::max<int>(m_width, _hdr.get().length() + 2);
402 _hdr.width(_w);
403
404 m_order.push_back(m_name);
405 auto _h = insert(m_name, m_headers);
406 auto _n = m_headers[_h].second.size();
407 _hdr.center(true);
408 _hdr.row(0);
409 _hdr.column(_n);
410 m_headers[_h].second.push_back(_hdr);
411 }
412
413 void operator()(entry _obj)
414 {
415 if(_obj.get().empty() && !_obj.permit_empty())
416 throw std::runtime_error("Entry has no value");
417
418 auto _w = std::max<int>(m_width, _obj.get().length() + 2);
419 _w = std::max<int>(_w, _obj.get_header().width());
420
421 _obj.width(_w);
422 _obj.get_header().width(_w);
423
424 auto _o = index(m_name, m_order);
425 if(_o < 0)
426 throw std::runtime_error(string_t("Missing entry for ") + m_name);
427
428 auto _r = insert(m_name, m_entries);
429 _obj.center(false);
430 _obj.row(m_rows + 1);
431 _obj.column(m_cols);
432 m_entries[_r].second.push_back(_obj);
433 ++m_cols;
434 }
435
436 friend std::ostream& operator<<(std::ostream& os, const stream& obj)
437 {
438 // return if completely empty
439 if(obj.m_headers.empty())
440 return os;
441
442 // return if not entries
443 if(obj.m_entries.empty())
444 return os;
445
448
449 obj.write_banner(ss);
450
451 obj.write_separator(ss, '-');
452
453 int64_t norder_col = 0;
454 for(const auto& itr : obj.m_order)
455 {
456 int64_t col = ++norder_col;
457
458 stringstream_t _ss;
459 // NOLINTNEXTLINE
460 auto _key = itr;
461 auto _offset = offset[_key]++;
462 auto _idx = index(_key, obj.m_headers);
463 if(_idx < 0 ||
464 (_idx >= 0 && !(_offset < (int) obj.m_headers[_idx].second.size())))
465 {
466 throw std::runtime_error("Error! indexing issue!");
467 }
468
469 const auto& hitr = obj.m_headers[_idx].second.at(_offset);
470 base::write_entry(_ss, hitr);
471
472 ss << obj.delim() << ' ' << _ss.str() << ' ';
473
474 if(obj.m_break.count(col) > 0)
475 break;
476 }
477
478 // end the line
479 ss << obj.delim() << '\n';
480
481 obj.write_separator(ss, obj.m_delim);
482
483 auto write_empty = [&](stringstream_t& _ss, int64_t _hidx, int64_t _offset) {
484 const auto& _hitr = obj.m_headers[_hidx].second;
485 auto _hsize = _hitr.size();
486 const auto& _hdr = _hitr.at(_offset % _hsize);
487 _ss << obj.delim() << ' ' << std::setw(_hdr.width() - 2) << "" << ' ';
488 };
489
490 offset.clear();
491
492 for(int i = 0; i < obj.m_rows; ++i)
493 {
494 bool just_broke = false;
495 norder_col = 0;
496 for(const auto& itr : obj.m_order)
497 {
498 just_broke = false;
499 int64_t col = ++norder_col;
500
501 stringstream_t _ss;
502 auto _key = itr; // NOLINT
503 auto _offset = offset[_key]++;
504
505 auto _hidx = index(_key, obj.m_headers);
506 auto _eidx = index(_key, obj.m_entries);
507
508 if(_eidx < 0 && _hidx >= 0)
509 {
510 write_empty(ss, _hidx, _offset);
511 }
512 else
513 {
514 assert(_hidx >= 0);
515 assert(_eidx >= 0);
516
517 const auto& _eitr = obj.m_entries[_eidx].second;
518 auto _esize = _eitr.size();
519 const auto& _itr = _eitr.at(_offset % _esize);
520
521 base::write_entry(_ss, _itr);
522 ss << obj.delim() << ' ' << _ss.str() << ' ';
523 }
524
525 // printf("column: %i, order size: %i, count: %i\n", col,
526 // obj.m_order.size(),
527 // obj.m_break.count(col));
528 if(col < (int64_t) obj.m_order.size() && obj.m_break.count(col) > 0)
529 {
530 ss << obj.m_delim << '\n';
531 just_broke = true;
532 for(auto j = obj.m_prefix_begin; j < obj.m_prefix_end; ++j)
533 write_empty(ss, j, 0);
534 }
535 }
536 if(!just_broke)
537 ss << obj.m_delim << '\n';
538
539 if(obj.m_separator_freq > 0)
540 {
541 if((i + 1) < obj.m_rows &&
542 (i % obj.m_separator_freq) == (obj.m_separator_freq - 1))
543 obj.write_separator(ss, obj.m_delim);
544 }
545 }
546
547 obj.write_separator(ss, '-');
548
549 os << ss.str();
550 return os;
551 }
552
553 template <typename StreamT>
554 void write_separator(StreamT& os, char _delim) const
555 {
558 ss.fill(m_fill);
559
560 int64_t norder_col = 0;
561 for(const auto& _key : m_order)
562 {
563 int64_t col = ++norder_col;
564 stringstream_t _ss;
565 auto _offset = offset[_key]++;
566 auto _hidx = index(_key, m_headers);
567 assert(_hidx >= 0);
568 const auto& _hitr = m_headers[_hidx].second;
569 auto _hsize = _hitr.size();
570 const auto& _hdr = _hitr.at(_offset % _hsize);
571 auto _w = _hdr.width();
572 if(col == 1)
573 {
574 ss << m_delim << std::setw(_w) << "";
575 }
576 else
577 {
578 ss << _delim << std::setw(_w) << "";
579 }
580 if(m_break.count(col) > 0)
581 break;
582 }
583
584 ss << m_delim << '\n';
585 os << ss.str();
586 }
587
588 template <typename StreamT>
589 void write_banner(StreamT& os) const
590 {
591 if(m_banner.length() == 0)
592 return;
593
594 write_separator(os, '-');
595
597
598 int64_t tot_w = 0;
599 int64_t norder_col = 0;
600 for(const auto& _key : m_order)
601 {
602 int64_t col = ++norder_col;
603 auto _offset = offset[_key]++;
604 auto _hidx = index(_key, m_headers);
605 assert(_hidx >= 0);
606 const auto& _hitr = m_headers[_hidx].second;
607 auto _hsize = _hitr.size();
608 const auto& _hdr = _hitr.at(_offset % _hsize);
609 tot_w += _hdr.width() + 1;
610 if(m_break.count(col) > 0)
611 break;
612 }
613
614 auto _trim = [&](string_t _banner) {
615 // trim the banner
616 if(_banner.length() > static_cast<size_t>(tot_w))
617 {
618 auto _hlen = (tot_w / 2) - 4; // half-length
619 auto _beg = _banner.substr(0, _hlen);
620 auto _end = _banner.substr(_banner.length() - _hlen);
621 _banner = _beg + "..." + _end;
622 }
623 return _banner;
624 };
625
626 auto _delim = delimit(m_banner, " \t");
627 std::vector<std::string> r_banner(1, "");
628 for(auto itr : _delim)
629 {
630 itr = _trim(itr);
631 auto nlen = r_banner.back().length() + itr.length() + 2;
632 if(nlen >= static_cast<size_t>(tot_w))
633 r_banner.emplace_back("");
634 if(r_banner.back().empty())
635 {
636 r_banner.back() += itr;
637 }
638 else
639 {
640 r_banner.back() += " " + itr;
641 }
642 }
643
645
646 auto _write_row = [&](const string_t& _banner) {
647 auto obeg = tot_w / 2;
648 obeg -= _banner.length() / 2;
649 obeg += _banner.length();
650 auto oend = tot_w - obeg;
651
652 ss << m_delim << std::setw(obeg) << std::right << _banner << std::setw(oend)
653 << std::right << m_delim << '\n';
654 };
655
656 for(const auto& itr : r_banner)
657 _write_row(itr);
658
659 os << ss.str();
660 }
661
662 template <typename... Tp, template <typename...> class _Tuple, size_t... Idx>
663 static void write(stream&, const _Tuple<Tp...>&, index_sequence<Idx...>);
664
665 void clear()
666 {
667 m_name = "";
668 m_headers.clear();
669 m_entries.clear();
670 }
671
672 header& get_header(const string_t& _key, int64_t _n)
673 {
674 auto idx = index(_key, m_headers);
675 if(idx < 0)
676 {
678 ss << "Missing header '" << _key << "'";
679 throw std::runtime_error(ss.str());
680 }
681
682 if(!(_n < (int64_t) m_headers[idx].second.size()))
683 {
684 auto _size = m_headers[idx].second.size();
685 return m_headers[idx].second[_n % _size];
686 }
687
688 return m_headers[idx].second[_n];
689 }
690
691 /// \fn int stream::add_row()
692 /// \brief indicate that a row of data has been finished
694 {
695 m_cols = 0;
696 return ++m_rows;
697 }
698
699 /// \fn void stream::sort(sorter, keys, exclude)
700 /// \brief Provide a \param sorter functor that operates on all or a specific
701 /// set of header keys. If \param keys is empty, all header keys are sorted.
702 /// If \param keys is non-empty, the sorted keys are placed at the front of the
703 /// container and any remaining keys not list in \param exclude will be added to the
704 /// end of the container in the order consistent with the origial construction
705 void sort(const std::function<bool(const std::string&, const std::string&)>& sorter,
706 std::vector<std::string> keys = {},
707 const std::set<std::string>& exclude = {})
708 {
709 // if no keys were provided, add all of them
710 if(keys.empty())
711 {
712 for(const auto& itr : m_order)
713 keys.push_back(itr);
714 }
715
716 // the new headers
717 order_map_t _order{};
718
719 // sort the keys
720 std::sort(keys.begin(), keys.end(), sorter);
721
722 // generate the new layout in the order specified
723 for(const auto& itr : keys)
724 {
725 bool found = false;
726 for(auto hitr = m_order.begin(); hitr != m_order.end(); ++hitr)
727 {
728 if(*hitr == itr)
729 {
730 _order.push_back(*hitr);
731 // remove entry
732 m_order.erase(hitr);
733 found = true;
734 break;
735 }
736 }
737 if(!found)
738 {
739 PRINT_HERE("Warning! Expected header tag '%s' not found when sorting",
740 itr.c_str());
741 }
742 }
743
744 // insert any remaining not excluded
745 for(const auto& itr : m_order)
746 {
747 if(exclude.count(itr) == 0)
748 _order.push_back(itr);
749 }
750
751 // set the new headers
752 m_order = _order;
753 }
754
755private:
756 bool m_center = false;
757 char m_fill = '-';
758 char m_delim = '|';
759 int m_width = 0;
760 int m_precision = 0;
761 int m_rows = 0;
762 int m_cols = 0;
763 int64_t m_prefix_begin = 0;
764 int64_t m_prefix_end = 0;
765 int64_t m_separator_freq = separator_frequency();
766 format_flags m_format = {};
767 string_t m_name = {};
768 string_t m_banner = {};
769 header_map_t m_headers = {};
770 entry_map_t m_entries = {};
771 order_map_t m_order = {};
772 break_set_t m_break = {};
773};
774
775//--------------------------------------------------------------------------------------//
776
777template <typename Tp>
779{
780 using format_flags = std::ios_base::fmtflags;
781
782 header_stream(format_flags _fmt, int _width, int _prec, bool _center)
783 : m_center(_center)
784 , m_width(_width)
785 , m_precision(_prec)
786 , m_format(_fmt)
787 {}
788
789 template <typename StreamT>
790 StreamT& operator()(StreamT& _os, const Tp& _obj)
791 {
792 _os << header(_obj, m_format, m_width, m_precision, m_center);
793 return _os;
794 }
795
800};
801
802//--------------------------------------------------------------------------------------//
803
804template <typename... ArgsT>
805void
806write_header(stream& _os, const std::string& _label, std::ios_base::fmtflags _fmt = {},
807 int _width = 0, int _prec = 0, bool _center = true)
808{
809 _os.set_name(_label);
810 _os(header(_label, _fmt, _width, _prec, _center));
811}
812
813//--------------------------------------------------------------------------------------//
814
815template <typename Tp>
816void
817write_entry(stream& _os, const std::string& _label, const Tp& _value, bool c = false,
818 bool l = false)
819{
820 _os.set_name(_label);
821 _os(entry(_value, _os.get_header(_label, 0), c, l));
822}
823
824//--------------------------------------------------------------------------------------//
825
826inline void
827write_entry(stream& _os, const std::string& _label, const std::string& _value,
828 bool c = false, bool = false)
829{
830 _os.set_name(_label);
831 _os(entry(_value, _os.get_header(_label, 0), c, true));
832}
833
834//--------------------------------------------------------------------------------------//
835
836template <typename Tp>
837void
838write_entry(stream& _os, const std::vector<std::string>& _label, const Tp& _value,
839 bool c = false, bool l = false)
840{
841 write_entry(_os, _label.front(), _value, c, l);
842}
843
844//--------------------------------------------------------------------------------------//
845
846template <typename Tp>
847void
848write_entry(stream& _os, const std::string& _label,
849 const std::vector<std::string>& _value, bool c = false, bool l = false)
850{
851 for(const auto& itr : _value)
852 write_entry(_os, _label, itr, c, l);
853}
854
855//--------------------------------------------------------------------------------------//
856
857template <typename Tp, typename Up>
858void
859write_entry(stream& _os, const std::string& _label, const std::pair<Tp, Up>& _value,
860 bool c = false, bool l = false)
861{
862 write_entry(_os, _label, _value.first, c, l);
863 write_entry(_os, _label, _value.second, c, l);
864}
865
866//--------------------------------------------------------------------------------------//
867
868template <typename Tp, typename Up>
869void
870write_entry(stream& _os, const std::vector<std::string>& _labels,
871 const std::pair<Tp, Up>& _value, bool c = false, bool l = false)
872{
873 size_t _L = _labels.size();
874 write_entry(_os, _labels.at(0), _value.first, c, l);
875 write_entry(_os, _labels.at(1 % _L), _value.second, c, l);
876}
877
878//--------------------------------------------------------------------------------------//
879
880template <typename Tp, typename... Alloc>
881void
882write_entry(stream& _os, const std::string& _label,
883 const std::vector<Tp, Alloc...>& _values, bool c = false, bool l = false)
884{
885 for(const auto& itr : _values)
886 write_entry(_os, _label, itr, c, l);
887}
888
889//--------------------------------------------------------------------------------------//
890
891template <typename Tp, typename... Alloc>
892void
893write_entry(stream& _os, const std::vector<std::string>& _labels,
894 const std::vector<Tp, Alloc...>& _values, bool c = false, bool l = false)
895{
896 size_t _L = _labels.size();
897 size_t N = _values.size();
898 for(size_t i = 0; i < N; ++i)
899 write_entry(_os, _labels.at(i % _L), _values.at(i), c, l);
900}
901
902//--------------------------------------------------------------------------------------//
903
904template <typename Tp, size_t N>
905void
906write_entry(stream& _os, const std::string& _label, const std::array<Tp, N>& _values,
907 bool c = false, bool l = false)
908{
909 for(const auto& itr : _values)
910 write_entry(_os, _label, itr, c, l);
911}
912
913//--------------------------------------------------------------------------------------//
914
915template <typename Tp, size_t N>
916void
917write_entry(stream& _os, const std::vector<std::string>& _labels,
918 const std::array<Tp, N>& _values, bool c = false, bool l = false)
919{
920 size_t _L = _labels.size();
921 for(size_t i = 0; i < N; ++i)
922 write_entry(_os, _labels.at(i % _L), _values.at(i), c, l);
923}
924
925//--------------------------------------------------------------------------------------//
926
927template <typename... Types, size_t... Idx>
928void
929write_entry(stream& _os, const std::string& _label, const std::tuple<Types...>& _values,
930 index_sequence<Idx...>, bool c = false, bool l = false)
931{
932 TIMEMORY_FOLD_EXPRESSION(write_entry(_os, _label, std::get<Idx>(_values), c, l));
933}
934
935//--------------------------------------------------------------------------------------//
936
937template <typename... Types, size_t... Idx>
938void
939write_entry(stream& _os, const std::vector<std::string>& _labels,
940 const std::tuple<Types...>& _values, index_sequence<Idx...>, bool c = false,
941 bool l = false)
942{
943 size_t _L = _labels.size();
945 write_entry(_os, _labels.at(Idx % _L), std::get<Idx>(_values), c, l));
946}
947
948//--------------------------------------------------------------------------------------//
949
950template <typename... Types>
951void
952write_entry(stream& _os, const std::string& _labels, const std::tuple<Types...>& _values,
953 bool c = false, bool l = false)
954{
955 constexpr size_t N = sizeof...(Types);
956 write_entry(_os, _labels, _values, make_index_sequence<N>{}, c, l);
957}
958
959//--------------------------------------------------------------------------------------//
960
961template <typename... Types>
962void
963write_entry(stream& _os, const std::vector<std::string>& _labels,
964 const std::tuple<Types...>& _values, bool c = false, bool l = false)
965{
966 constexpr size_t N = sizeof...(Types);
967 write_entry(_os, _labels, _values, make_index_sequence<N>{}, c, l);
968}
969
970//--------------------------------------------------------------------------------------//
971
972} // namespace data
973
974//--------------------------------------------------------------------------------------//
975namespace utility
976{
977//
978// backwards-compatibility
979//
983//
984template <typename Tp>
986//
987template <typename... Args>
988auto
989write_header(Args&&... args)
990{
991 return data::write_header(std::forward<Args>(args)...);
992}
993//
994template <typename... Args>
995auto
996write_entry(Args&&... args)
997{
998 return data::write_entry(std::forward<Args>(args)...);
999}
1000//
1001} // namespace utility
1002
1003//--------------------------------------------------------------------------------------//
1004
1005} // namespace tim
std::string string_t
Definition: library.cpp:57
void write_header(stream &_os, const std::string &_label, std::ios_base::fmtflags _fmt={}, int _width=0, int _prec=0, bool _center=true)
Definition: stream.hpp:806
void write_entry(stream &_os, const std::string &_label, const Tp &_value, bool c=false, bool l=false)
Definition: stream.hpp:817
auto write_header(Args &&... args)
Definition: stream.hpp:989
data::entry entry
Definition: stream.hpp:980
data::header header
Definition: stream.hpp:981
data::stream stream
Definition: stream.hpp:982
auto write_entry(Args &&... args)
Definition: stream.hpp:996
Definition: kokkosp.cpp:39
std::make_integer_sequence< size_t, Num > make_index_sequence
Alias template make_index_sequence.
Definition: types.hpp:182
separator_frequency
Definition: settings.cpp:1785
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
const std::string std::ostream * os
max_width
Definition: settings.cpp:1645
std::integer_sequence< size_t, Idx... > index_sequence
Alias template index_sequence.
Definition: types.hpp:178
ContainerT delimit(const std::string &line, const std::string &delimiters="\"',;: ", PredicateT &&predicate=[](const std::string &s) -> std::string { return s;})
Definition: delimit.hpp:68
Definition: stream.hpp:56
stream_entry & operator=(stream_entry &&)=default
int column() const
Definition: stream.hpp:83
stream_entry & operator=(const stream_entry &)=default
void precision(int v)
Definition: stream.hpp:92
bool center() const
Definition: stream.hpp:79
stream_entry(int _row=-1, int _col=-1, format_flags _fmt={}, int _width=0, int _prec=0, bool _center=false)
Definition: stream.hpp:61
void left(bool v)
Definition: stream.hpp:88
format_flags m_format
Definition: stream.hpp:134
std::stringstream stringstream_t
Definition: stream.hpp:58
void center(bool v)
Definition: stream.hpp:87
~stream_entry()=default
int m_width
Definition: stream.hpp:132
int width() const
Definition: stream.hpp:82
format_flags flags() const
Definition: stream.hpp:85
std::string string_t
Definition: stream.hpp:57
int m_precision
Definition: stream.hpp:133
bool m_left
Definition: stream.hpp:129
void row(int v)
Definition: stream.hpp:89
friend bool operator<(const stream_entry &lhs, const stream_entry &rhs)
Definition: stream.hpp:121
stream_entry(const stream_entry &)=default
int m_column
Definition: stream.hpp:131
bool m_center
Definition: stream.hpp:128
int m_row
Definition: stream.hpp:130
void width(int v)
Definition: stream.hpp:90
void setf(format_flags v)
Definition: stream.hpp:93
string_t m_value
Definition: stream.hpp:135
void column(int v)
Definition: stream.hpp:91
string_t get() const
Definition: stream.hpp:77
void operator()(const string_t &val)
Definition: stream.hpp:95
int precision() const
Definition: stream.hpp:84
void construct(const Tp &val)
Definition: stream.hpp:98
std::ios_base::fmtflags format_flags
Definition: stream.hpp:59
bool left() const
Definition: stream.hpp:80
int row() const
Definition: stream.hpp:81
stream_entry(stream_entry &&)=default
~entry()=default
void setf(format_flags v)
Definition: stream.hpp:256
entry & operator=(const entry &)=default
int width() const
Definition: stream.hpp:249
header & get_header()
Definition: stream.hpp:259
bool permit_empty() const
Definition: stream.hpp:248
entry & operator=(entry &&)=default
void precision(int v)
Definition: stream.hpp:255
format_flags flags() const
Definition: stream.hpp:251
const header & get_header() const
Definition: stream.hpp:258
entry(const std::string &_val, header &_hdr, bool _center=false, bool _left=true)
Definition: stream.hpp:227
entry(entry &&)=default
int precision() const
Definition: stream.hpp:250
void width(int v)
Definition: stream.hpp:254
entry(Tp &&_val, header &_hdr, bool _center=false, bool _left=false)
Definition: stream.hpp:217
void permit_empty(bool v)
Definition: stream.hpp:253
entry(const entry &_rhs)
Definition: stream.hpp:238
std::ios_base::fmtflags format_flags
Definition: stream.hpp:780
header_stream(format_flags _fmt, int _width, int _prec, bool _center)
Definition: stream.hpp:782
format_flags m_format
Definition: stream.hpp:799
StreamT & operator()(StreamT &_os, const Tp &_obj)
Definition: stream.hpp:790
header(const std::string &_val, format_flags _fmt={}, int _width=0, int _prec=0, bool _center=true)
Definition: stream.hpp:196
header & operator=(const header &)=default
header(const Tp &_val, format_flags _fmt, int _width, int _prec, bool _center=true)
Definition: stream.hpp:204
header(header &&)=default
header(const header &)=default
header & operator=(header &&)=default
vector_t< header_pair_t > header_map_t
Definition: stream.hpp:293
void width(int v)
Definition: stream.hpp:320
char delim() const
Definition: stream.hpp:314
void set_prefix_begin(int val=-1)
Definition: stream.hpp:381
void delim(char v)
Definition: stream.hpp:321
std::pair< K, M > pair_t
Definition: stream.hpp:277
void operator()(entry _obj)
Definition: stream.hpp:413
void setf(format_flags v)
Definition: stream.hpp:322
vector_t< entry_pair_t > entry_map_t
Definition: stream.hpp:294
static int64_t & separator_frequency()
Definition: stream.hpp:298
std::map< K, M > map_t
Definition: stream.hpp:274
void set_banner(string_t v)
Definition: stream.hpp:328
vector_t< header > header_col_t
Definition: stream.hpp:287
stream(char _delim='|', char _fill='-', format_flags _fmt={}, int _width=0, int _prec=0, bool _center=false)
Definition: stream.hpp:301
int add_row()
indicate that a row of data has been finished
Definition: stream.hpp:693
void insert_break(int val=-1)
Definition: stream.hpp:391
int64_t freq() const
Definition: stream.hpp:316
int width() const
Definition: stream.hpp:313
vector_t< string_t > order_map_t
Definition: stream.hpp:285
void write_separator(StreamT &os, char _delim) const
Definition: stream.hpp:554
bool center() const
Definition: stream.hpp:311
static int64_t index(const string_t &_val, const vector_t< pair_t< string_t, vector_t< Tp > > > &_obj)
Definition: stream.hpp:354
static int64_t index(const string_t &_val, const vector_t< string_t > &_obj)
Definition: stream.hpp:330
std::vector< T > vector_t
Definition: stream.hpp:280
int precision() const
Definition: stream.hpp:312
format_flags flags() const
Definition: stream.hpp:315
std::stringstream stringstream_t
Definition: stream.hpp:283
void set_prefix_end(int val=-1)
Definition: stream.hpp:386
void set_name(string_t v)
Definition: stream.hpp:326
static int64_t insert(const string_t &_val, vector_t< pair_t< string_t, vector_t< Tp > > > &_obj)
Definition: stream.hpp:366
void sort(const std::function< bool(const std::string &, const std::string &)> &sorter, std::vector< std::string > keys={}, const std::set< std::string > &exclude={})
Provide a.
Definition: stream.hpp:705
void operator()(header _hdr)
Definition: stream.hpp:396
vector_t< entry > entry_col_t
Definition: stream.hpp:288
pair_t< string_t, header_col_t > header_pair_t
Definition: stream.hpp:290
static void write(stream &, const _Tuple< Tp... > &, index_sequence< Idx... >)
void precision(int v)
Definition: stream.hpp:319
set_t< int > break_set_t
Definition: stream.hpp:295
void write_banner(StreamT &os) const
Definition: stream.hpp:589
std::ios_base::fmtflags format_flags
Definition: stream.hpp:284
static int64_t insert(const string_t &_val, vector_t< string_t > &_obj)
Definition: stream.hpp:340
std::set< T > set_t
Definition: stream.hpp:271
void center(bool v)
Definition: stream.hpp:318
header & get_header(const string_t &_key, int64_t _n)
Definition: stream.hpp:672
std::string string_t
Definition: stream.hpp:282
pair_t< string_t, entry_col_t > entry_pair_t
Definition: stream.hpp:291
void setfreq(int64_t v)
Definition: stream.hpp:323
friend std::ostream & operator<<(std::ostream &os, const stream &obj)
Definition: stream.hpp:436
#define PRINT_HERE(...)
Definition: macros.hpp:152
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56