62 int _width = 0,
int _prec = 0,
bool _center =
false)
81 TIMEMORY_NODISCARD
int row()
const {
return m_row; }
97 template <
typename Tp>
124 : (lhs.
row() < rhs.
row());
140template <
typename StreamT,
typename Tp>
142write_entry(StreamT& ss,
const Tp& obj)
144 using stringstream_t = std::stringstream;
146 auto itr = obj.get();
148 if(obj.row() == 0 || obj.center())
150 int _w = obj.width();
151 int _i = itr.length();
153 int _ihalf = (_i + 1) / 2;
154 int _wrem = (_whalf - _ihalf);
155 _wrem = std::max<int>(_wrem, 0);
156 if(_i + _wrem > _w - 3)
159 if(((_wrem - itr.length()) - (_w - 2)) > 1)
161 stringstream_t ssbeg;
162 ssbeg << std::setw(_wrem) <<
"" << itr;
163 ss << std::left << std::setw(_w - 2) << ssbeg.str();
167 if(obj.column() == 0 || obj.left())
170 _ss << std::left << itr;
171 int remain = obj.width() - _ss.str().length() - 2;
172 ss << _ss.str() << std::setw(remain) <<
"";
176 ss << std::right << std::setw(obj.width() - 2) << itr;
197 int _prec = 0,
bool _center =
true)
203 template <
typename Tp>
206 : base::
stream_entry(0, -1, _fmt, _width, _prec, _center)
216 template <
typename Tp>
217 explicit entry(Tp&& _val,
header& _hdr,
bool _center =
false,
bool _left =
false)
231 , m_permit_empty(
true)
248 TIMEMORY_NODISCARD
bool permit_empty()
const {
return m_permit_empty; }
249 TIMEMORY_NODISCARD
int width()
const {
return m_hdr->
width(); }
263 bool m_permit_empty =
false;
270 template <
typename T>
273 template <
typename K,
typename M>
276 template <
typename K,
typename M>
279 template <
typename T>
302 int _width = 0,
int _prec = 0,
bool _center =
false)
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; }
316 TIMEMORY_NODISCARD int64_t
freq()
const {
return m_separator_freq; }
323 void setfreq(int64_t v) { m_separator_freq = v; }
332 for(
size_t i = 0; i < _obj.size(); ++i)
334 if(_obj.at(i) == _val)
335 return static_cast<int64_t
>(i);
342 auto idx =
index(_val, _obj);
346 _obj.push_back(_val);
348 printf(
"> inserted '%s'...\n", _val.c_str());
353 template <
typename Tp>
357 for(
size_t i = 0; i < _obj.size(); ++i)
359 if(_obj.at(i).first == _val)
360 return static_cast<int64_t
>(i);
365 template <
typename Tp>
369 auto idx =
index(_val, _obj);
373 _obj.resize(_obj.size() + 1);
374 _obj[idx].first = _val;
376 printf(
"[%s]> inserted '%s'...\n", demangle<Tp>().c_str(), _val.c_str());
383 m_prefix_begin = (val < 0) ? ((
int) m_order.size()) : val;
388 m_prefix_end = (val < 0) ? ((
int) m_order.size()) : val;
393 m_break.insert((val < 0) ? ((
int) m_order.size()) : val);
398 if(_hdr.
get().empty())
399 throw std::runtime_error(
"Header has no value");
401 auto _w = std::max<int>(m_width, _hdr.
get().length() + 2);
404 m_order.push_back(m_name);
405 auto _h =
insert(m_name, m_headers);
406 auto _n = m_headers[_h].second.size();
410 m_headers[_h].second.push_back(_hdr);
416 throw std::runtime_error(
"Entry has no value");
418 auto _w = std::max<int>(m_width, _obj.
get().length() + 2);
424 auto _o =
index(m_name, m_order);
426 throw std::runtime_error(
string_t(
"Missing entry for ") + m_name);
428 auto _r =
insert(m_name, m_entries);
430 _obj.
row(m_rows + 1);
432 m_entries[_r].second.push_back(_obj);
439 if(obj.m_headers.empty())
443 if(obj.m_entries.empty())
453 int64_t norder_col = 0;
454 for(
const auto& itr : obj.m_order)
456 int64_t col = ++norder_col;
461 auto _offset = offset[_key]++;
462 auto _idx =
index(_key, obj.m_headers);
464 (_idx >= 0 && !(_offset < (
int) obj.m_headers[_idx].second.size())))
466 throw std::runtime_error(
"Error! indexing issue!");
469 const auto& hitr = obj.m_headers[_idx].second.at(_offset);
470 base::write_entry(_ss, hitr);
472 ss << obj.
delim() <<
' ' << _ss.str() <<
' ';
474 if(obj.m_break.count(col) > 0)
479 ss << obj.
delim() <<
'\n';
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) <<
"" <<
' ';
492 for(
int i = 0; i < obj.m_rows; ++i)
494 bool just_broke =
false;
496 for(
const auto& itr : obj.m_order)
499 int64_t col = ++norder_col;
503 auto _offset = offset[_key]++;
505 auto _hidx =
index(_key, obj.m_headers);
506 auto _eidx =
index(_key, obj.m_entries);
508 if(_eidx < 0 && _hidx >= 0)
510 write_empty(ss, _hidx, _offset);
517 const auto& _eitr = obj.m_entries[_eidx].second;
518 auto _esize = _eitr.size();
519 const auto& _itr = _eitr.at(_offset % _esize);
521 base::write_entry(_ss, _itr);
522 ss << obj.
delim() <<
' ' << _ss.str() <<
' ';
528 if(col < (int64_t) obj.m_order.size() && obj.m_break.count(col) > 0)
530 ss << obj.m_delim <<
'\n';
532 for(
auto j = obj.m_prefix_begin; j < obj.m_prefix_end; ++j)
533 write_empty(ss, j, 0);
537 ss << obj.m_delim <<
'\n';
539 if(obj.m_separator_freq > 0)
541 if((i + 1) < obj.m_rows &&
542 (i % obj.m_separator_freq) == (obj.m_separator_freq - 1))
553 template <
typename StreamT>
560 int64_t norder_col = 0;
561 for(
const auto& _key : m_order)
563 int64_t col = ++norder_col;
565 auto _offset = offset[_key]++;
566 auto _hidx =
index(_key, m_headers);
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();
574 ss << m_delim << std::setw(_w) <<
"";
578 ss << _delim << std::setw(_w) <<
"";
580 if(m_break.count(col) > 0)
584 ss << m_delim <<
'\n';
588 template <
typename StreamT>
591 if(m_banner.length() == 0)
599 int64_t norder_col = 0;
600 for(
const auto& _key : m_order)
602 int64_t col = ++norder_col;
603 auto _offset = offset[_key]++;
604 auto _hidx =
index(_key, m_headers);
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)
614 auto _trim = [&](
string_t _banner) {
616 if(_banner.length() >
static_cast<size_t>(tot_w))
618 auto _hlen = (tot_w / 2) - 4;
619 auto _beg = _banner.substr(0, _hlen);
620 auto _end = _banner.substr(_banner.length() - _hlen);
621 _banner = _beg +
"..." + _end;
626 auto _delim =
delimit(m_banner,
" \t");
627 std::vector<std::string> r_banner(1,
"");
628 for(
auto itr : _delim)
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())
636 r_banner.back() += itr;
640 r_banner.back() +=
" " + itr;
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;
652 ss << m_delim << std::setw(obeg) << std::right << _banner << std::setw(oend)
653 << std::right << m_delim <<
'\n';
656 for(
const auto& itr : r_banner)
662 template <
typename... Tp,
template <
typename...>
class _Tuple,
size_t... Idx>
674 auto idx =
index(_key, m_headers);
678 ss <<
"Missing header '" << _key <<
"'";
679 throw std::runtime_error(ss.str());
682 if(!(_n < (int64_t) m_headers[idx].second.size()))
684 auto _size = m_headers[idx].second.size();
685 return m_headers[idx].second[_n % _size];
688 return m_headers[idx].second[_n];
706 std::vector<std::string> keys = {},
707 const std::set<std::string>& exclude = {})
712 for(
const auto& itr : m_order)
720 std::sort(keys.begin(), keys.end(), sorter);
723 for(
const auto& itr : keys)
726 for(
auto hitr = m_order.begin(); hitr != m_order.end(); ++hitr)
730 _order.push_back(*hitr);
739 PRINT_HERE(
"Warning! Expected header tag '%s' not found when sorting",
745 for(
const auto& itr : m_order)
747 if(exclude.count(itr) == 0)
748 _order.push_back(itr);
756 bool m_center =
false;
763 int64_t m_prefix_begin = 0;
764 int64_t m_prefix_end = 0;
777template <
typename Tp>
789 template <
typename StreamT>
804template <
typename... ArgsT>
807 int _width = 0,
int _prec = 0,
bool _center =
true)
810 _os(
header(_label, _fmt, _width, _prec, _center));
815template <
typename Tp>
828 bool c =
false,
bool =
false)
836template <
typename Tp>
839 bool c =
false,
bool l =
false)
846template <
typename Tp>
849 const std::vector<std::string>& _value,
bool c =
false,
bool l =
false)
851 for(
const auto& itr : _value)
857template <
typename Tp,
typename Up>
860 bool c =
false,
bool l =
false)
868template <
typename Tp,
typename Up>
871 const std::pair<Tp, Up>& _value,
bool c =
false,
bool l =
false)
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);
880template <
typename Tp,
typename... Alloc>
883 const std::vector<Tp, Alloc...>& _values,
bool c =
false,
bool l =
false)
885 for(
const auto& itr : _values)
891template <
typename Tp,
typename... Alloc>
894 const std::vector<Tp, Alloc...>& _values,
bool c =
false,
bool l =
false)
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);
904template <
typename Tp,
size_t N>
907 bool c =
false,
bool l =
false)
909 for(
const auto& itr : _values)
915template <
typename Tp,
size_t N>
918 const std::array<Tp, N>& _values,
bool c =
false,
bool l =
false)
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);
927template <
typename... Types,
size_t... Idx>
937template <
typename... Types,
size_t... Idx>
943 size_t _L = _labels.size();
945 write_entry(_os, _labels.at(Idx % _L), std::get<Idx>(_values), c, l));
950template <
typename... Types>
953 bool c =
false,
bool l =
false)
955 constexpr size_t N =
sizeof...(Types);
961template <
typename... Types>
964 const std::tuple<Types...>& _values,
bool c =
false,
bool l =
false)
966 constexpr size_t N =
sizeof...(Types);
984template <
typename Tp>
987template <
typename... Args>
994template <
typename... Args>
void write_header(stream &_os, const std::string &_label, std::ios_base::fmtflags _fmt={}, int _width=0, int _prec=0, bool _center=true)
void write_entry(stream &_os, const std::string &_label, const Tp &_value, bool c=false, bool l=false)
auto write_header(Args &&... args)
auto write_entry(Args &&... args)
std::make_integer_sequence< size_t, Num > make_index_sequence
Alias template make_index_sequence.
tim::mpl::apply< std::string > string
const std::string std::ostream * os
std::integer_sequence< size_t, Idx... > index_sequence
Alias template index_sequence.
ContainerT delimit(const std::string &line, const std::string &delimiters="\"',;: ", PredicateT &&predicate=[](const std::string &s) -> std::string { return s;})
stream_entry & operator=(stream_entry &&)=default
stream_entry & operator=(const stream_entry &)=default
stream_entry(int _row=-1, int _col=-1, format_flags _fmt={}, int _width=0, int _prec=0, bool _center=false)
std::stringstream stringstream_t
format_flags flags() const
friend bool operator<(const stream_entry &lhs, const stream_entry &rhs)
stream_entry(const stream_entry &)=default
void setf(format_flags v)
void operator()(const string_t &val)
void construct(const Tp &val)
std::ios_base::fmtflags format_flags
stream_entry(stream_entry &&)=default
void setf(format_flags v)
entry & operator=(const entry &)=default
bool permit_empty() const
entry & operator=(entry &&)=default
format_flags flags() const
const header & get_header() const
entry(const std::string &_val, header &_hdr, bool _center=false, bool _left=true)
entry(Tp &&_val, header &_hdr, bool _center=false, bool _left=false)
void permit_empty(bool v)
vector_t< header_pair_t > header_map_t
void set_prefix_begin(int val=-1)
void operator()(entry _obj)
void setf(format_flags v)
vector_t< entry_pair_t > entry_map_t
static int64_t & separator_frequency()
void set_banner(string_t v)
vector_t< header > header_col_t
stream(char _delim='|', char _fill='-', format_flags _fmt={}, int _width=0, int _prec=0, bool _center=false)
int add_row()
indicate that a row of data has been finished
void insert_break(int val=-1)
vector_t< string_t > order_map_t
void write_separator(StreamT &os, char _delim) const
static int64_t index(const string_t &_val, const vector_t< pair_t< string_t, vector_t< Tp > > > &_obj)
static int64_t index(const string_t &_val, const vector_t< string_t > &_obj)
std::vector< T > vector_t
format_flags flags() const
std::stringstream stringstream_t
void set_prefix_end(int val=-1)
void set_name(string_t v)
static int64_t insert(const string_t &_val, vector_t< pair_t< string_t, vector_t< Tp > > > &_obj)
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.
void operator()(header _hdr)
vector_t< entry > entry_col_t
pair_t< string_t, header_col_t > header_pair_t
static void write(stream &, const _Tuple< Tp... > &, index_sequence< Idx... >)
void write_banner(StreamT &os) const
std::ios_base::fmtflags format_flags
static int64_t insert(const string_t &_val, vector_t< string_t > &_obj)
header & get_header(const string_t &_key, int64_t _n)
pair_t< string_t, entry_col_t > entry_pair_t
friend std::ostream & operator<<(std::ostream &os, const stream &obj)
#define TIMEMORY_FOLD_EXPRESSION(...)