Walker test code coverage report
Current view: top level - Base - Print.hpp (source / functions) Hit Total Coverage
Commit: test_coverage.info Lines: 117 152 77.0 %
Date: 2022-09-21 13:52:12 Functions: 57 64 89.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 192 620 31.0 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Base/Print.hpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     General purpose pretty printer functionality
       9                 :            :   \details   This file contains general purpose printer functions. Using the
      10                 :            :     functions defined here provides formatting, and a consistent look with
      11                 :            :     simple client-side code. For formatting, the Boost Format library is used,
      12                 :            :     see http://www.boost.org/doc/libs/release/libs/format.
      13                 :            : */
      14                 :            : // *****************************************************************************
      15                 :            : #ifndef Print_h
      16                 :            : #define Print_h
      17                 :            : 
      18                 :            : #include <iostream>
      19                 :            : #include <sstream>
      20                 :            : #include <iomanip>
      21                 :            : #include <cmath>
      22                 :            : #include <array>
      23                 :            : #include <vector>
      24                 :            : #include <algorithm>
      25                 :            : #include <unordered_map>
      26                 :            : 
      27                 :            : #include "NoWarning/format.hpp"
      28                 :            : 
      29                 :            : #include "Timer.hpp"
      30                 :            : #include "Exception.hpp"
      31                 :            : #include "Has.hpp"
      32                 :            : #include "ChareState.hpp"
      33                 :            : #include "PrintUtil.hpp"
      34                 :            : #include "TeeBuf.hpp"
      35                 :            : 
      36                 :            : namespace tk {
      37                 :            : 
      38                 :            : //! Output verbosity. C-style enum as this is used for template argument.
      39                 :            : enum Style { QUIET=0, VERBOSE=1 };
      40                 :            : 
      41                 :            : //! Pretty printer base. Contains general purpose printer functions. Using the
      42                 :            : //! functions defined here provides formatting, and a consistent look with
      43                 :            : //! simple client-side code. For formatting, the Boost Format library is used,
      44                 :            : //! see http://www.boost.org/doc/libs/release/libs.
      45                 :            : class Print {
      46                 :            : 
      47                 :            :   public:
      48                 :            :     //! Constructor: Quiet output by default, only stuff written to qstr shown.
      49                 :            :     //! \details Instantiate with str = std::cout for verbose output. Any
      50                 :            :     //  member function can be called by overriding the default stream via the
      51                 :            :     //  template argument, Style, a C-style enum. Note: By default, str ==
      52                 :            :     //  std::clog.  This is used to initialize str to a local stringstream into
      53                 :            :     //  which all verbose output goes by default, i.e., it will not be shown.
      54                 :            :     //  This solution is chosen instead of trickery with null-streams, as
      55                 :            :     //  boost:formatted output into null-streams caused invalid reads in
      56                 :            :     //  valgrind. This way quiet output (formatted or not) simply goes into a
      57                 :            :     //  local stringstream. In other words, the default argument to str,
      58                 :            :     //  std::clog, is only used to detect whether client code passed a default
      59                 :            :     //  argument or not: if it did not, the string stream is used for verbose
      60                 :            :     //  output, if it did, the specified stream is used for the verbose output.
      61                 :            :     //! \param[in] screen Screen output filename. If an empty string is passed,
      62                 :            :     //!   it is assumed that client code does not want to save the stream into
      63                 :            :     //!   a file.
      64                 :            :     //! \param[in,out] str Verbose stream
      65                 :            :     //! \param[in] mode Open mode for screen output file, see
      66                 :            :     //!   http://en.cppreference.com/w/cpp/io/ios_base/openmode
      67                 :            :     //! \param[in,out] qstr Quiet stream
      68                 :       5489 :     explicit Print( const std::string& screen = {},
      69                 :            :                     std::ostream& str = std::clog,
      70                 :            :                     std::ios_base::openmode mode = std::ios_base::out,
      71                 :       5489 :                     std::ostream& qstr = std::cout ) :
      72                 :            :       m_null(),
      73         [ +  + ]:       5489 :       m_stream( str.rdbuf() == std::clog.rdbuf() ? m_null : str ),
      74                 :            :       m_qstream( qstr ),
      75                 :            :       m_file( screen, mode ),
      76                 :       4845 :       m_tee(m_file.rdbuf(), screen.empty() ? m_file.rdbuf() : m_stream.rdbuf()),
      77 [ +  - ][ +  - ]:      21956 :       m_ssa( screen.empty() ? m_file : m_stream, &m_tee ) {}
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
      78                 :            : 
      79                 :            :     //! Save pointer to stream. This function, used in conjunction with reset(),
      80                 :            :     //! can be used to pass streams around. This is not possible in general,
      81                 :            :     //! since streams are not copyable. See this in action in, e.g.,
      82                 :            :     //! Control/Walker/CmdLine/Parser.C.
      83                 :            :     //! \return The internal stream buffer of the stream
      84                 :            :     template< Style s = VERBOSE >
      85                 :        197 :     std::streambuf* save() const { return stream<s>().rdbuf(); }
      86                 :            : 
      87                 :            :     //! Reset stream to streambuf given. This function, used in conjunction with
      88                 :            :     //! save(), can be used to pass streams around. This is not possible in
      89                 :            :     //! general, since streams are not copyable. See this in action in, e.g.,
      90                 :            :     //! Control/Walker/CmdLine/Parser.C.
      91                 :            :     //! \param[in] buf Stream buffer of a stream
      92                 :            :     //! \return The internal stream buffer of the stream
      93                 :            :     template< Style s = VERBOSE >
      94                 :        197 :     std::streambuf* reset( std::streambuf* buf ) {
      95                 :        197 :       if (stream<s>().rdbuf() == std::cout.rdbuf())
      96                 :          0 :         m_qstream << "Warning: overwriting std::cout! Doing as requested...\n";
      97                 :        394 :       return stream<s>().rdbuf( buf );
      98                 :            :     }
      99                 :            : 
     100                 :            :     //! Operator << for printing any type to the verbose stream.
     101                 :            :     //! \param[in] os Reference to pretty printer object
     102                 :            :     //! \param[in] t Reference to an arbitrary object of type T. T must define
     103                 :            :     //! operator<< for std::ostream-compatible streams.
     104                 :            :     //! \return The internal stream buffer of the stream
     105                 :            :     template< typename T >
     106                 :            :     friend const Print& operator<<( const Print& os, const T& t )
     107 [ +  - ][ +  - ]:       5623 :     { os.m_stream << t; return os; }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     108                 :            : 
     109                 :            :     //! Operator % for printing any type to the quiet stream.
     110                 :            :     //! \param[in] os Reference to pretty printer object
     111                 :            :     //! \param[in] t Reference to an arbitrary object of type T. T must define
     112                 :            :     //! operator<< for std::ostream-compatible streams.
     113                 :            :     //! \return The internal stream buffer of the stream
     114                 :            :     template< typename T >
     115                 :            :     friend const Print& operator%( const Print& os, const T& t )
     116 [ +  - ][ -  - ]:          3 :     { os.m_qstream << t; return os; }
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     117                 :            : 
     118                 :            :     //! Operator % for a function pointer taking ostream returning ostream.
     119                 :            :     //! This is so that several of operators of % can be chained together.
     120                 :            :     //! \param[in] os Reference to pretty printer object
     121                 :            :     //! \param[in] pf Function pointer taking a reference to std::ostream and
     122                 :            :     //!   returning a reference to std::ostream
     123                 :            :     //! \return Reference to pretty printer object
     124                 :            :     friend const Print& operator%( const Print& os,
     125         [ -  - ]:          0 :       std::ostream& (*pf)(std::ostream&) ) { os.m_qstream << pf; return os; }
     126                 :            : 
     127                 :            :     //! Operator << for a function pointer taking ostream returning ostream.
     128                 :            :     //! This is so that several of operators of << can be chained together.
     129                 :            :     //! \param[in] os Reference to pretty printer object
     130                 :            :     //! \param[in] pf Function pointer taking a reference to std::ostream and
     131                 :            :     //!   returning a reference to std::ostream
     132                 :            :     //! \return Reference to pretty printer object
     133                 :            :     friend const Print& operator<<( const Print& os,
     134         [ +  - ]:       1699 :       std::ostream& (*pf)(std::ostream&) ) { os.m_stream << pf; return os; }
     135                 :            : 
     136                 :            :     //! Formatted print of part header: title.
     137                 :            :     //! \param[in] t Part title to be printed
     138                 :            :     template< Style s = VERBOSE >
     139                 :        299 :     void part( const std::string& t ) const {
     140                 :        299 :       std::size_t half_length = t.size()/2;
     141                 :        299 :       std::string left( half_length+1, '-' );
     142         [ +  + ]:        299 :       std::string right( (t.size()%2) ? (half_length+1) : half_length, '-' );
     143 [ +  - ][ +  - ]:        598 :       std::string underline( left + " o " + right );
         [ +  - ][ -  - ]
     144                 :            :       std::string upper( t );
     145                 :            :       std::transform( begin(t), end(t), begin(upper), ::toupper );
     146 [ +  - ][ +  - ]:        598 :       upper = "< " + upper + " >";
         [ -  + ][ -  - ]
     147         [ +  - ]:        299 :       stream<s>() << m_part_fmt % upper;
     148         [ +  - ]:        299 :       stream<s>() << m_part_underline_fmt % underline;
     149                 :        299 :     }
     150                 :            : 
     151                 :            :     //! Formatted print of section header: t.
     152                 :            :     //! \param[in] t Section title to be printed
     153                 :            :     template< Style s = VERBOSE >
     154                 :       1065 :     void section( const std::string& t ) const {
     155                 :       1065 :       stream<s>() << m_section_title_fmt % m_section_indent % m_section_bullet
     156                 :            :                      % t;
     157 [ +  - ][ +  - ]:       2130 :       stream<s>() << m_section_underline_fmt % m_section_indent
     158                 :       1065 :                % std::string( m_section_indent.size() + 2 + t.size(), '-' );
     159                 :       1065 :     }
     160                 :            : 
     161                 :            :     //! Formatted print of section header: title : value.
     162                 :            :     //! \param[in] name Section title to be printed
     163                 :            :     //! \param[in] value Section value to be printed
     164                 :            :     template< Style s = VERBOSE >
     165                 :         94 :     void section( const std::string& name, const std::string& value ) const {
     166                 :         94 :       stream<s>() << m_section_title_value_fmt % m_section_indent
     167                 :         94 :                      % m_section_bullet % name % value;
     168 [ +  - ][ +  - ]:        188 :       stream<s>() << m_section_underline_fmt % m_section_indent
     169                 :         94 :                      % std::string( m_section_indent.size() + 3 + name.size() +
     170                 :            :                                     value.size(), '-' );
     171                 :         94 :     }
     172                 :            : 
     173                 :            :     //! Formatted print of subsection header: title.
     174                 :            :     //! \param[in] t Subsection title to be printed
     175                 :            :     template< Style s = VERBOSE >
     176                 :        118 :     void subsection( const std::string& t ) const {
     177                 :        118 :       stream<s>() << m_subsection_title_fmt % m_subsection_indent
     178                 :        118 :                      % m_subsection_bullet % t;
     179                 :        118 :     }
     180                 :            : 
     181                 :            :     //! Formatted print of title.
     182                 :            :     //! \param[in] value Title string to be printed
     183                 :            :     template< Style s = VERBOSE >
     184                 :         99 :     void title( const std::string& value ) const {
     185                 :            :       // clean up white spaces and format title with no indent or line-break
     186 [ +  - ][ +  - ]:        297 :       auto t = splitLines( value, "", "", 10000 );
         [ -  + ][ -  + ]
         [ +  - ][ -  - ]
                 [ -  - ]
     187         [ +  - ]:         99 :       stream<s>() << m_section_title_value_fmt % m_section_indent
     188                 :         99 :                      % m_section_bullet % "Title" % t;
     189 [ +  - ][ +  - ]:        198 :       stream<s>() << m_section_underline_fmt % m_section_indent
     190 [ +  - ][ +  + ]:        198 :                      % std::string( m_section_indent.size()+8+t.size(), '-' );
                 [ -  - ]
     191                 :         99 :     }
     192                 :            : 
     193                 :            :     //! Formatted print of item: name.
     194                 :            :     //! \param[in] name Item name to be printed
     195                 :            :     template< Style s = VERBOSE >
     196                 :         99 :     void item( const std::string& name ) const
     197                 :         99 :     { stream<s>() << m_item_name_fmt % m_item_indent % name; }
     198                 :            : 
     199                 :            :     //! Formatted print of item: name : value
     200                 :            :     //! \param[in] name Item name to be printed
     201                 :            :     //! \param[in] value Item value to be printed
     202                 :            :     template< Style s = VERBOSE, typename T >
     203                 :       3598 :     void item( const std::string& name, const T& value ) const
     204                 :       3598 :     { stream<s>() << m_item_name_value_fmt % m_item_indent % name % value; }
     205                 :            : 
     206                 :            :     //! Formatted print of item with wide name: name : value
     207                 :            :     //! \param[in] name Long item name to be printed
     208                 :            :     //! \param[in] value Item value to be printed
     209                 :            :     template< Style s = VERBOSE, typename T >
     210                 :            :     void longitem( const std::string& name, const T& value ) const
     211                 :            :     { stream<s>() << m_item_longname_value_fmt % m_item_indent % name % value; }
     212                 :            : 
     213                 :            :     //! Formatted print of item: name : bool
     214                 :            :     //! \param[in] name Item name to be printed
     215                 :            :     //! \param[in] b Item value as bool to be printed
     216                 :            :     //! \details boost::format does not directly support std::boolalpha, so it
     217                 :            :     //!   must be done via boost::io::group, hence this overload for when the
     218                 :            :     //!   item value to be printed is of type bool, which will print true/false
     219                 :            :     //!   instead of 1/0.
     220                 :            :     //! \see https://stackoverflow.com/a/13709726
     221                 :            :     template< Style s = VERBOSE >
     222                 :            :     void item( const std::string& name, bool b ) const
     223                 :            :     { stream<s>() << m_item_name_value_fmt % m_item_indent % name %
     224                 :            :                      boost::io::group(std::boolalpha, b); }
     225                 :            : 
     226                 :            :     //! Formatted print of item: h:m:s.
     227                 :            :     //! \param[in] name Item name to be printed
     228                 :            :     //! \param[in] watch Watch (in hours, minutes, seconds) to be printed as
     229                 :            :     //!   item value
     230                 :            :     template< Style s = VERBOSE >
     231                 :        199 :     void item( const std::string& name, const tk::Timer::Watch& watch ) const {
     232                 :        199 :       stream<s>() << m_item_name_watch_fmt % m_item_indent % name
     233                 :        199 :                    % watch.hrs.count() % watch.min.count() % watch.sec.count();
     234                 :        199 :     }
     235                 :            : 
     236                 :            :     //! Formatted print of a performance statistic (an item of a list)
     237                 :            :     //! \param[in] name Performance statistic name to be printed
     238                 :            :     //! \param[in] value Performance statistic value
     239                 :            :     template< Style s = VERBOSE >
     240                 :            :     void perfitem( const std::string& name, tk::real value ) const
     241                 :            :     { stream<s>() << m_item_name_perf_fmt % m_item_indent % name % value; }
     242                 :            : 
     243                 :            :     //! Formatted print of a list: name: entries...
     244                 :            :     //! \param[in] name Name of a section (consisting of a list) to be printed
     245                 :            :     //! \param[in] entries Container of type Container whose elements to be
     246                 :            :     //!   printed. Container must be iterable, e.g., possible to be used in a
     247                 :            :     //!   range-based for loop. \see
     248                 :            :     //!   http://en.cppreference.com/w/cpp/language/range-for
     249                 :            :     template< Style s = VERBOSE, class Container >
     250         [ +  - ]:         97 :     void list( const std::string& name, const Container& entries ) const {
     251         [ +  - ]:         97 :       if (!entries.empty()) {
     252                 :         97 :         section<s>( name );
     253         [ +  + ]:        230 :         for (auto& e : entries)
     254                 :        133 :           stream<s>() << m_list_item_fmt % m_item_indent % e;
     255                 :            :       }
     256                 :         97 :     }
     257                 :            : 
     258                 :            :     //! Formatted print of a list: name: option names...
     259                 :            :     //! \param[in] t Title of the section containing a list
     260                 :            :     //! \param[in] factory Factory (an std::map) whose values are printed
     261                 :            :     //!   interpreted as options (classes deriving from Toggle), defining the
     262                 :            :     //!   name querying member function name().
     263                 :            :     template< class Option, Style s = VERBOSE, class Factory >
     264         [ +  - ]:          5 :     void list( const std::string& t, const Factory& factory ) const {
     265         [ +  - ]:          5 :       if ( !factory.empty() ) {
     266                 :          5 :         section<s>( t );
     267                 :          5 :         Option option;
     268         [ +  + ]:         20 :         for (const auto& f : factory)
     269 [ +  - ][ +  - ]:         30 :           stream<s>() << m_list_item_fmt % m_item_indent % option.name(f.first);
     270                 :            :       }
     271                 :          5 :     }
     272                 :            : 
     273                 :            :     //! Formatted print of elapsed times
     274                 :            :     //! \param[in] t Title of section containing a list of elapsed times
     275                 :            :     //! \param[in] clock std::vector of strings (clock names) and associated
     276                 :            :     //!   timers which could be in various formats as long as there is a
     277                 :            :     //!   corresponding item() overload that can apply operator << for outputing
     278                 :            :     //!   their value to an output stream. Examples of allowed ClockFormats are:
     279                 :            :     //!   tk::Timer::Watch, which is a struct containing a timestamp in h:m:s
     280                 :            :     //!   format, and the return value of Timer::dsec(), which is a tk::real.
     281                 :            :     template< Style s = VERBOSE, class ClockFormat >
     282                 :        100 :     void time( const std::string& t,
     283                 :            :                const std::vector<
     284                 :            :                  std::pair< std::string, ClockFormat > >& clock ) const
     285                 :            :     {
     286                 :        100 :       section<s>( t );
     287         [ +  + ]:        300 :       for (const auto& c : clock) item<s>( c.first, c.second );
     288                 :        100 :     }
     289                 :            : 
     290                 :            :     //! Formatted print of performance statistics
     291                 :            :     //! \param[in] t Title of section containing a list of performance stats
     292                 :            :     //! \param[in] stat std::vector of strings (names of a performance
     293                 :            :     //!   statistics) and associated values.
     294                 :            :     template< Style s = VERBOSE >
     295                 :            :     void perf( const std::string& t,
     296                 :            :                const std::vector< std::pair< std::string, tk::real > >& stat )
     297                 :            :     const
     298                 :            :     {
     299                 :            :       if (!stat.empty()) {
     300                 :            :         section<s>( t );
     301                 :            :         for (const auto& c : stat) perfitem<s>( c.first, c.second );
     302                 :            :       }
     303                 :            :     }
     304                 :            : 
     305                 :            :     //! Formatted print of a note
     306                 :            :     //! \param[in] msg Message to print as a note
     307                 :            :     template< Style s = VERBOSE >
     308                 :         96 :     void note( const std::string& msg ) const
     309                 :         96 :     { stream<s>() << m_note_fmt % m_item_indent % msg; }
     310                 :            : 
     311                 :            :     //! Echo formatted print of a diagnostics message
     312                 :            :     //! \param[in] msg Message to print as a diagnostics message
     313                 :            :     template< Style s = VERBOSE >
     314                 :         93 :     void diag( const std::string& msg ) const
     315                 :         93 :     { stream<s>() << m_diag_fmt % msg << std::flush; }
     316                 :            : 
     317                 :            :     //! Echo formatted print of a diagnostics message within a progress section
     318                 :            :     //! \param[in] labels Label parts of diagnostics message
     319                 :            :     //! \param[in] values Value parts of diagnostics message
     320                 :            :     //! \param[in] precr If true start with a CR/LF, if false end with it
     321                 :            :     //! \note The number of labels and values must equal.
     322                 :            :     template< Style s = VERBOSE >
     323                 :            :     void diag( const std::vector< std::string >& labels,
     324                 :            :                const std::vector< std::string >& values,
     325                 :            :                bool precr = true ) const
     326                 :            :     {
     327                 :            :       Assert( labels.size() == values.size(), "Size mismatch" );
     328                 :            :       if (!labels.empty()) {
     329                 :            :         stream<s>() << (precr ? "\n" : "") <<
     330                 :            :           m_inprog_diag_fmt % labels[0] % values[0];
     331                 :            :         for (std::size_t i=1; i<labels.size(); ++i)
     332                 :            :           stream<s>() << m_inprog_extra_diag_fmt % labels[i] % values[i];
     333                 :            :         stream<s>() << (precr ? " " : "\n") << std::flush;
     334                 :            :       }
     335                 :            :     }
     336                 :            : 
     337                 :            :     //! Start formatted print of a diagnostics message
     338                 :            :     //! Start formatted print of a diagnostics message
     339                 :            :     //! \param[in] msg First part of message to print as a diagnostics message
     340                 :            :     template< Style s = VERBOSE >
     341                 :            :     void diagstart( const std::string& msg ) const
     342                 :            :     { stream<s>() << m_diag_start_fmt % msg << std::flush; }
     343                 :            : 
     344                 :            :     //! Finish formatted print of a diagnostics message
     345                 :            :     //! \param[in] msg Last part of message to print as a diagnostics message
     346                 :            :     template< Style s = VERBOSE >
     347                 :            :     void diagend( const std::string& msg ) const
     348                 :            :     { stream<s>() << m_diag_end_fmt % msg << std::flush; }
     349                 :            : 
     350                 :            :     //! Print chare state collected
     351                 :            :     //! \param[in] state State map to print
     352                 :            :     template< Style s = VERBOSE >
     353                 :          0 :     void charestate( const std::unordered_map< int,
     354                 :            :                         std::vector< ChareState > >& state ) const
     355                 :            :     {
     356                 :          0 :       stream<s>() << m_charestate_frame_fmt %
     357                 :            :                      "\n>>> =========== CHARE STATE ==========\n>>>";
     358                 :            :       // Group state by chare id
     359                 :            :       std::map< int, std::vector< ChareState > > sorted_state;
     360         [ -  - ]:          0 :       for (const auto& p : state)
     361         [ -  - ]:          0 :         for (const auto& i : p.second)
     362 [ -  - ][ -  - ]:          0 :           sorted_state[ i.get< tag::id >() ].push_back( i );
     363                 :            :       // Sort states by time stamp
     364         [ -  - ]:          0 :       for (auto& p : sorted_state)
     365                 :          0 :         std::sort( begin(p.second), end(p.second),
     366                 :            :                    []( const ChareState& a, const ChareState& b )
     367 [ -  - ][ -  - ]:          0 :                      { return a.get< tag::time >() < b.get< tag::time >(); } );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     368                 :            :       // Output states
     369                 :            :       std::size_t q = 0;
     370         [ -  - ]:          0 :       for (const auto& p : sorted_state) {
     371         [ -  - ]:          0 :         for (const auto& i : p.second) {
     372         [ -  - ]:          0 :           stream<s>() << m_charestate_fmt % i.get< tag::ch >()
     373         [ -  - ]:          0 :                                           % p.first
     374                 :            :                                           % i.get< tag::fn >()
     375                 :            :                                           % i.get< tag::pe >()
     376                 :            :                                           % i.get< tag::it >()
     377                 :            :                                           % i.get< tag::time >();
     378                 :            :         }
     379         [ -  - ]:          0 :         if (++q != sorted_state.size())
     380         [ -  - ]:          0 :            stream<s>() << m_charestate_frame_fmt % "";
     381                 :            :       }
     382         [ -  - ]:          0 :       stream<s>() << m_charestate_frame_fmt %
     383                 :            :                      "\n>>> ======= END OF CHARE STATE =======\n>>>";
     384                 :          0 :     }
     385                 :            : 
     386                 :            :     //! Echo formatted print of a progress message
     387                 :            :     //! \param[in] prefix Strings to output prefixing the progress report
     388                 :            :     //! \param[in] done Array of integers indicating how many have been done
     389                 :            :     //! \param[in] max Array of integers indicating how many to be done
     390                 :            :     //! \param[in] progress_size Size of previous progress report (to overwrite)
     391                 :            :     //! \details All input arrays are the same size. The prefix strings
     392                 :            :     //!   are optional, i.e., they can be empty strings. The function generates
     393                 :            :     //!   an output to the stream configured in the following fashion:
     394                 :            :     //!   pre1[done1/max1], pre2[done2/max2], ..., e.g., r:[1/3], b[2/8].
     395                 :            :     //!   Whenever this function is called, a number of backspaces are put into
     396                 :            :     //!   the stream so that the new progress report string overwrites the old
     397                 :            :     //!   one. In order to backtrack the correct amount, the length of the old
     398                 :            :     //!   progress report is stored (by whatever object holds us) and passed in
     399                 :            :     //!   by reference in progress_size, which is overwritten here once it has
     400                 :            :     //!   been used for backtracking. Therefore, for restarting a new series of
     401                 :            :     //!   progress reports, this variable must be zeroed. Also, it is best to
     402                 :            :     //!   not to interleave multiple tasks, because even if a different
     403                 :            :     //!   progress_size is kept for each, there is no regard as to which line we
     404                 :            :     //!   output to in the stream. In other words, multiple task outputs will
     405                 :            :     //!   be intermingled, leading to confusing screen output.
     406                 :            :     template< std::size_t N, Style s = VERBOSE >
     407                 :            :     void progress( const std::array< std::string, N >& prefix,
     408                 :            :                    const std::array< int, N >& done,
     409                 :            :                    const std::array< int, N >& max,
     410                 :            :                    std::size_t& progress_size ) const
     411                 :            :     {
     412                 :            :       // lambda to determine the number of digits in an integer
     413                 :            :       auto numdig = []( int i ) -> std::size_t {
     414                 :            :         return i > 0 ?
     415                 :            :           static_cast< std::size_t >( std::log10(static_cast<double>(i)) ) + 1
     416                 :            :           : 1; };
     417                 :            :       // Backspace so that new progress can overwrite old one
     418                 :            :       stream<s>() << std::string( progress_size, '\b' );
     419                 :            :       std::stringstream ss;
     420                 :            :       auto ip = prefix.cbegin();
     421                 :            :       auto id = done.cbegin();
     422                 :            :       auto im = max.cbegin();
     423                 :            :       progress_size = 0;
     424                 :            :       while (ip != prefix.cend()) {
     425                 :            :         // Compute new length of progress string
     426                 :            :         progress_size += 4 + ip->size() + numdig(*id) + numdig(*im);
     427                 :            :         // Construct and output new progress string to stream
     428                 :            :         ss << *ip << ":[" << *id << '/' << *im << ']';
     429                 :            :         ++ip; ++id; ++im;
     430                 :            :         // if next subprogress is not the last one, put in a comma
     431                 :            :         if (ip != prefix.cend()) {
     432                 :            :           ss << ", ";
     433                 :            :           progress_size += 2;
     434                 :            :         } else {
     435                 :            :           ss << ' ';
     436                 :            :           ++progress_size;
     437                 :            :         }
     438                 :            :       }
     439                 :            :       stream<s>() << m_progress_fmt % ss.str() << std::flush;
     440                 :            :     }
     441                 :            : 
     442                 :            :     //! \brief Formatted print of help of one-liners on all command-line
     443                 :            :     //!   parameters or control file keywords
     444                 :            :     //! \param[in] executable Name of executable to output help for
     445                 :            :     //! \param[in] pool std::map of keywords and their associated information
     446                 :            :     //! \param[in] msg Message to print after exectuable in the title
     447                 :            :     //! \param[in] pfx Prefix in front of alias, double prefix in front of
     448                 :            :     //!   keyword
     449                 :            :     template< Style s = VERBOSE, class Help >
     450                 :          1 :     void help( const std::string& executable,
     451                 :            :                const Help& pool,
     452                 :            :                const std::string& msg,
     453                 :            :                const std::string& pfx = "" ) const
     454                 :            :     {
     455                 :          1 :       stream<s>() << m_help_title_fmt % executable % msg;
     456         [ +  + ]:         11 :       for (const auto& keyword : pool) {
     457                 :            :         const auto& info = keyword.second;
     458                 :            :         const auto& alias = info.alias;
     459                 :            :         const auto& expt = info.expt;
     460         [ +  - ]:         10 :         stream<s>() << m_help_item_fmt
     461 [ +  - ][ +  - ]:         50 :                        % std::string( ( alias ? pfx + *alias + ", " : "") +
         [ +  - ][ -  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     462 [ +  - ][ +  - ]:         30 :                                         pfx + pfx + keyword.first )
         [ +  - ][ -  + ]
                 [ -  - ]
     463         [ +  + ]:         20 :                        % (expt ? *expt : "")
     464                 :         10 :                        % info.shortDescription;
     465                 :            :       }
     466                 :          1 :     }
     467                 :            : 
     468                 :            :     //! Print version information
     469                 :            :     //! \param[in] executable Name of executable to output license for
     470                 :            :     //! \param[in] ver Version to output
     471                 :            :     //! \param[in] copyright Copyright info to output
     472                 :            :     template< Style s = VERBOSE >
     473                 :          0 :     void version( const std::string& executable,
     474                 :            :                   const std::string& ver,
     475                 :            :                   const std::string& copyright ) const
     476                 :          0 :     { stream<s>() << m_version_fmt % executable % ver % copyright; }
     477                 :            : 
     478                 :            :     //! Print license information
     479                 :            :     //! \param[in] executable Name of executable to output license for
     480                 :            :     //! \param[in] lic License info to output
     481                 :            :     template< Style s = VERBOSE >
     482                 :            :     void license( const std::string& executable,
     483                 :            :                   const std::string& lic ) const
     484                 :            :     { stream<s>() << m_license_fmt % executable % lic; }
     485                 :            : 
     486                 :            :     //! Print mandatory arguments information
     487                 :            :     //! \param[in] args Mandaatory-arguments infor to output
     488                 :            :     template< Style s = VERBOSE >
     489                 :          0 :     void mandatory( const std::string& args ) const
     490                 :          0 :     { stream<s>() << m_mandatory_fmt % args; }
     491                 :            : 
     492                 :            :     //! Print example usage information
     493                 :            :     //! \param[in] executable Name of executable to output usage info for
     494                 :            :     //! \param[in] example Example command line to output
     495                 :            :     //! \param[in] msg Message to output after example
     496                 :            :     template< Style s = VERBOSE >
     497                 :          0 :     void usage( const std::string& executable,
     498                 :            :                 const std::string& example,
     499                 :            :                 const std::string& msg ) const
     500                 :          0 :     { stream<s>() << m_usage_fmt % executable % example % msg; }
     501                 :            : 
     502                 :            :     //! Print lower and upper bounds for a keyword if defined
     503                 :            :     template< Style s = VERBOSE, typename Info >
     504         [ -  + ]:          1 :     void bounds( const Info& info ) const {
     505         [ -  + ]:          1 :       if (info.lower)
     506         [ -  - ]:          0 :         stream<s>() << m_description_fmt
     507 [ -  - ][ -  - ]:          0 :           % splitLines( *info.lower, m_subsection_indent, "Lower bound: " );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     508         [ -  + ]:          1 :       if (info.upper)
     509         [ -  - ]:          0 :         stream<s>() << m_description_fmt
     510 [ -  - ][ -  - ]:          0 :           % splitLines( *info.upper, m_subsection_indent, "Upper bound: " );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     511                 :          1 :     }
     512                 :            : 
     513                 :            :     //! \brief Formatted print of verbose help on a single command-line
     514                 :            :     //!   parameter or control file keyword
     515                 :            :     //! \param[in] executable Name of executable to output help for
     516                 :            :     //! \param[in] kw Keyword help struct on which help is to be printed
     517                 :            :     template< Style s = VERBOSE, class HelpKw >
     518                 :          1 :     void helpkw( const std::string& executable, const HelpKw& kw ) const {
     519                 :            :       Assert( !kw.keyword.empty(), "Empty keyword in Print::helpkw()" );
     520                 :          1 :       const auto& info = kw.info;
     521                 :            :       const auto& alias = info.alias;
     522                 :            :       const auto& expt = info.expt;
     523                 :            :       const auto& choices = info.choices;
     524                 :            :       // print keyword title
     525         [ +  - ]:          1 :       if (kw.cmd)
     526         [ +  - ]:          1 :         stream<s>() << m_helpkw_cmd_title_fmt
     527         [ +  - ]:          1 :                        % executable
     528 [ +  - ][ +  - ]:          3 :                        % (alias ? "-" + *alias + ", " : "")
         [ +  - ][ -  - ]
         [ +  - ][ -  - ]
     529                 :          1 :                        % kw.keyword;
     530                 :            :       else
     531                 :          0 :         stream<s>() << m_helpkw_ctr_title_fmt
     532                 :          0 :                        % executable
     533                 :          0 :                        % kw.keyword;
     534                 :            :       // print short description
     535         [ +  - ]:          1 :       stream<s>() << m_description_fmt
     536 [ +  - ][ +  - ]:          3 :                      % splitLines( info.shortDescription, m_subsection_indent );
         [ +  - ][ -  + ]
         [ -  + ][ -  - ]
         [ -  - ][ -  - ]
     537                 :            :       // print long description
     538         [ +  - ]:          1 :       stream<s>() << m_description_fmt
     539 [ +  - ][ +  - ]:          3 :                      % splitLines( info.longDescription, m_subsection_indent );
         [ -  + ][ -  + ]
         [ -  + ][ -  - ]
         [ -  - ][ -  - ]
     540                 :            :       // print expected type description
     541         [ -  + ]:          1 :       if (expt)
     542         [ -  - ]:          0 :         stream<s>() << m_description_fmt
     543 [ -  - ][ -  - ]:          0 :                        % splitLines( *expt, m_subsection_indent,
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     544                 :            :                                      "Expected type: " );
     545                 :            :       // print lower bound if defined
     546                 :          1 :       bounds< s >( info );
     547                 :            :       // print expected valied choices
     548         [ -  + ]:          1 :       if (choices)
     549         [ -  - ]:          0 :         stream<s>() << m_description_fmt
     550 [ -  - ][ -  - ]:          0 :                     % splitLines( *choices, m_subsection_indent,
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     551                 :            :                                   "Expected valid choices: ");
     552                 :          1 :     }
     553                 :            : 
     554                 :            :     //! Print end of a part
     555                 :            :     template< Style s = VERBOSE >
     556                 :        297 :     void endpart() const { stream<s>() << std::endl; }
     557                 :            : 
     558                 :            :     //! Print end of subsection
     559                 :            :     template< Style s = VERBOSE >
     560 [ +  + ][ +  - ]:        199 :     void endsubsection() const { stream<s>() << '\n'; }
                 [ -  - ]
     561                 :            : 
     562                 :            :     //! Print raw data to stream.
     563                 :            :     //! \param[in] r Arbitrary data of arbitrary type as long as it defines
     564                 :            :     //!   operator << for std::ostream.
     565                 :            :     template< Style s = VERBOSE, typename T >
     566                 :       2342 :     void raw( const T& r ) const { stream<s>() << r; }
     567                 :            : 
     568                 :            :     //! Return verbose or quiet stream depending on style template argument.
     569                 :            :     //! Non-const version.
     570                 :            :     //! \return Reference to underlying std::ostream.
     571                 :            :     template< Style s = VERBOSE >
     572 [ -  + ][ -  + ]:        199 :     std::ostream& stream() noexcept { return s ? m_stream : m_qstream; }
     573                 :            : 
     574                 :            :     //! Return verbose or quiet stream depending on style template argument.
     575                 :            :     //! Const version.
     576                 :            :     //! \return Reference to underlying std::ostream.
     577                 :            :     template< Style s = VERBOSE >
     578 [ +  - ][ +  + ]:      10515 :     std::ostream& stream() const noexcept { return s ? m_stream : m_qstream; }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  - ]
         [ -  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  - ]
     579                 :            : 
     580                 :            :     //! Function object for echoing policies to screen
     581                 :            :     struct echoPolicies {
     582                 :            :       //! Need to store reference to host class whose data we operate on
     583                 :            :       const Print* const m_host;
     584                 :            :       //! Constructor: store host object pointer
     585                 :         93 :       explicit echoPolicies( const Print* const host ) : m_host( host ) {}
     586                 :            :       //! Function call operator templated on the type that echos a policy
     587                 :       1581 :       template< typename U > void operator()( brigand::type_<U> ) {
     588                 :            :         static_assert( tk::HasTypedef_code_v< typename U::info >,
     589                 :            :                        "Policy code undefined for keyword" );
     590                 :            :         // Print policy code - policy name
     591 [ +  - ][ +  - ]:       4743 :         m_host->raw( m_host->m_item_indent + "   " +
         [ -  + ][ -  - ]
     592 [ +  - ][ +  - ]:       6324 :                      *U::code() + " - " + U::info::name() + '\n' );
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ -  + ][ +  + ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     593                 :            : 
     594                 :       1581 :       }
     595                 :            :     };
     596                 :            : 
     597                 :            :     //! Print RNGTest header. Text ASCII Art Generator used for executable
     598                 :            :     //! names: http://patorjk.com/software/taag.
     599                 :            :     template< Style s = VERBOSE >
     600                 :          5 :     void headerRNGTest() const {
     601                 :            :        stream<s>() << R"(
     602                 :            :  __      __        .__   __                  __   __________  _______    ___________________              __   
     603                 :            : /  \    /  \_____  |  | |  | __ ___________  \ \  \______   \ \      \  /  _____/\__    ___/___   _______/  |_ 
     604                 :            : \   \/\/   /\__  \ |  | |  |/ // __ \_  __ \  \ \  |       _/ /   |   \/   \  ___  |    |_/ __ \ /  ___/\   __\
     605                 :            :  \        /  / __ \|  |_|    <\  ___/|  | \/  / /  |    |   \/    |    \    \_\  \ |    |\  ___/ \___ \  |  |  
     606                 :            :   \__/\  /  (____  /____/__|_ \\___  >__|    /_/   |____|_  /\____|__  /\______  / |____| \___  >____  > |__|  
     607                 :            :        \/        \/          \/    \/                     \/         \/        \/             \/     \/)"
     608                 :            :       << std::endl;
     609                 :          5 :     }
     610                 :            : 
     611                 :            :     //! Print UnitTest header. Text ASCII Art Generator used for executable
     612                 :            :     //! names: http://patorjk.com/software/taag.
     613                 :            :     template< Style s = VERBOSE >
     614                 :          2 :     void headerUnitTest() const {
     615                 :            :        stream<s>() << R"(
     616                 :            :  __      __        .__   __                  __    ____ ___      .__  __ ___________              __   
     617                 :            : /  \    /  \_____  |  | |  | __ ___________  \ \  |    |   \____ |__|/  |\__    ___/___   _______/  |_ 
     618                 :            : \   \/\/   /\__  \ |  | |  |/ // __ \_  __ \  \ \ |    |   /    \|  \   __\|    |_/ __ \ /  ___/\   __\
     619                 :            :  \        /  / __ \|  |_|    <\  ___/|  | \/  / / |    |  /   |  \  ||  |  |    |\  ___/ \___ \  |  |  
     620                 :            :   \__/\  /  (____  /____/__|_ \\___  >__|    /_/  |______/|___|  /__||__|  |____| \___  >____  > |__|  
     621                 :            :        \/        \/          \/    \/                          \/                     \/     \/)"
     622                 :            :       << std::endl;
     623                 :          2 :     }
     624                 :            : 
     625                 :            :     //! Print Walker header. Text ASCII Art Generator used for executable names:
     626                 :            :     //! http://patorjk.com/software/taag.
     627                 :            :     template< Style s = VERBOSE >
     628                 :         94 :     void headerWalker() const {
     629                 :            :       stream<s>() << R"(
     630                 :            :  __      __        .__   __
     631                 :            : /  \    /  \_____  |  | |  | __ ___________
     632                 :            : \   \/\/   /\__  \ |  | |  |/ // __ \_  __ \
     633                 :            :  \        /  / __ \|  |_|    <\  ___/|  | \/
     634                 :            :   \__/\  /  (____  /____/__|_ \\___  >__|
     635                 :            :        \/        \/          \/    \/)"
     636                 :            :       << std::endl;
     637                 :         94 :     }
     638                 :            : 
     639                 :            :   protected:
     640                 :            :     //! Bullets
     641                 :            :     const char m_section_bullet = '*';
     642                 :            :     const char m_subsection_bullet = '<';
     643                 :            :     //! Indents
     644         [ +  - ]:       5489 :     const std::string m_section_indent = " ";
     645                 :            :     const std::string m_subsection_indent =
     646                 :            :       std::operator+(m_section_indent,"  ");
     647                 :            :     const std::string m_item_indent = std::operator+(m_subsection_indent,"  ");
     648                 :            : 
     649                 :            :     //! Format strings. See http://www.boost.org/doc/libs/release/libs/format.
     650                 :            :     using format = boost::format;
     651                 :            :     mutable format m_header_fmt = format("%|=80|\n");
     652                 :            :     mutable format m_part_fmt = format("\n%|=80|\n");
     653                 :            :     mutable format m_section_title_fmt = format("\n%s%c %s:\n");
     654                 :            :     mutable format m_section_title_value_fmt = format("\n%s%c %s: %s\n");
     655                 :            :     mutable format m_subsection_title_fmt = format("%s%c %s >\n");
     656                 :            :     mutable format m_list_item_fmt = format("%s%-40s\n");
     657                 :            :     mutable format m_note_fmt = format("%s%-40s\n");
     658                 :            :     mutable format m_diag_fmt = format("Walker> %s\n");
     659                 :            :     mutable format m_diag_start_fmt = format("Walker> %s ");
     660                 :            :     mutable format m_inprog_diag_fmt = format("Walker> %s: %s");
     661                 :            :     mutable format m_inprog_extra_diag_fmt = format(", %s: %s");
     662                 :            :     mutable format m_charestate_frame_fmt = format(">>> %s\n");
     663                 :            :     mutable format m_charestate_fmt =
     664                 :            :               format(">>> %s(%d)::%|-15| PE:%|-4| it:%|-5| t:%f\n");
     665                 :            :     mutable format m_diag_end_fmt = format("%s\n");
     666                 :            :     mutable format m_progress_fmt = format("%s");
     667                 :            :     mutable format m_help_title_fmt = format("\n%s %s\n");
     668                 :            :     mutable format m_help_item_fmt = format("%20s%11s %s\n");
     669                 :            :     mutable format m_helpkw_cmd_title_fmt =
     670                 :            :               format("\n%s command-line keyword %s--%s\n\n");
     671                 :            :     mutable format m_helpkw_ctr_title_fmt =
     672                 :            :               format("\n%s control file keyword '%s'\n\n");
     673                 :            :     mutable format m_helpkw_fmt = format("%s%s\n\n%s%s\n\n");
     674                 :            :     mutable format m_description_fmt = format("%s\n\n");
     675                 :            :     mutable format m_item_name_fmt = format("%s%-40s : ");
     676                 :            :     mutable format m_item_name_value_fmt = format("%s%-40s : %s\n");
     677                 :            :     mutable format m_item_longname_value_fmt = format("%s%-55s : %s\n");
     678                 :            :     mutable format m_item_name_watch_fmt = format("%s%-75s : %d:%d:%d\n");
     679                 :            :     mutable format m_item_name_perf_fmt = format("%s%-75s : %s\n");
     680                 :            :     mutable format m_item_widename_value_fmt = format("%s%-75s : %s\n");
     681                 :            :     mutable format m_part_underline_fmt = format("      %|=68|\n");
     682                 :            :     mutable format m_section_underline_fmt = format("%s%s\n");
     683                 :            :     mutable format m_version_fmt = format("\nWalker::%s, version %s\n%s\n\n");
     684                 :            :     mutable format m_license_fmt = format("\nWalker::%s\n\n%s\n\n");
     685                 :            :     mutable format m_mandatory_fmt = format("\n%s\n");
     686                 :            :     mutable format m_usage_fmt =
     687                 :            :               format("\n%s example usage:\n\n$ %s\n\n%s\n\n");
     688                 :            : 
     689                 :            :     // Stream objects
     690                 :            :     std::stringstream m_null;   //!< Default verbose stream
     691                 :            :     std::ostream& m_stream;     //!< Verbose stream
     692                 :            :     std::ostream& m_qstream;    //!< Quiet stream
     693                 :            : 
     694                 :            :   private:
     695                 :            :     std::ofstream m_file;       //!< File stream to save verbose stream in
     696                 :            :     tk::teebuf m_tee;           //!< Used to tie m_stream and m_file
     697                 :            :     tk::scoped_streambuf_assignment m_ssa;
     698                 :            : };
     699                 :            : 
     700                 :            : } // tk::
     701                 :            : 
     702                 :            : #endif // Print_h

Generated by: LCOV version 1.14