LCOV - code coverage report
Current view: top level - utilities/source - logger.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 43 59 72.9 %
Date: 2024-04-19 03:43:27 Functions: 1 2 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Jeroen Keiren
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file logger.cpp
      10             : 
      11             : #include "mcrl2/utilities/logger.h"
      12             : #include <cassert>
      13             : 
      14             : namespace mcrl2 {
      15             :   namespace log {
      16             : 
      17           0 :   std::string format_time(const time_t* t)
      18             :   {
      19             :     struct tm* r;
      20           0 :     r = localtime(t);
      21             : 
      22             :     char buffer[11];
      23           0 :     std::size_t res = strftime(buffer, sizeof(buffer), "%H:%M:%S", r);
      24           0 :     if(res == 0)
      25             :     {
      26           0 :       std::clog << "Could not write time to buffer" << std::endl;
      27           0 :       return std::string();
      28             :     }
      29           0 :     return buffer;
      30             :   }
      31             : 
      32        4245 :   std::string formatter::format(const log_level_t level, 
      33             :                                 const time_t timestamp, 
      34             :                                 const std::string& msg,
      35             :                                 const bool print_time_information)
      36             :   {
      37             :     // Construct the message header, with or without time and debug level info.
      38        4245 :     const bool print_log_level= level >= debug;
      39        4245 :     std::stringstream start_of_line;
      40        4245 :     if (print_time_information || print_log_level)
      41             :     {
      42        3714 :       start_of_line << "[";
      43             :     }
      44        4245 :     if (print_time_information)
      45             :     {
      46           0 :       start_of_line << format_time(&timestamp);
      47             :     }
      48        4245 :     if (print_time_information && print_log_level)
      49             :     {
      50           0 :       start_of_line << " ";
      51             :     }
      52        4245 :     if (print_log_level)
      53             :     {
      54        3714 :       start_of_line << log_level_to_string(level);
      55             :     }
      56        4245 :     if (print_time_information || print_log_level)
      57             :     {
      58        3714 :       start_of_line << "] ";
      59             :     }
      60        4245 :     if (print_log_level)
      61             :     {
      62        3714 :       start_of_line << std::string(7 - log_level_to_string(level).size(), ' ');
      63             :     }
      64             : 
      65             :     // Check if message is finished. We
      66        4245 :     bool msg_ends_with_newline = false;
      67        4245 :     if (msg.size() > 0)
      68             :     {
      69        4227 :       msg_ends_with_newline = (msg[msg.size()-1] == '\n');
      70             :     }
      71             : 
      72        4245 :     std::stringstream result;
      73             : 
      74             :     // Determine whether the last line should be overwritten (by inserting a
      75             :     // carriage return).
      76        4245 :     bool overwrite = false;
      77        4245 :     if (last_message_was_status())
      78             :     {
      79          18 :       if (level == status)
      80             :       {
      81          12 :         if (last_message_ended_with_newline())
      82             :         {
      83           0 :           if (msg != "\n")
      84             :           {
      85           0 :             result << "\r" << start_of_line.str();
      86           0 :             overwrite = true;
      87             :           }
      88             :           else
      89             :           {
      90           0 :             result << "\n";
      91             :           }
      92             :         }
      93             :       }
      94             :       else
      95             :       {
      96           6 :         result << "\n" << start_of_line.str();
      97             :       }
      98             :     }
      99             :     else
     100        4227 :     if (last_message_ended_with_newline())
     101             :     {
     102        4127 :       result << start_of_line.str();
     103             :     }
     104             : 
     105             :     // Copy the message to result, keeping track of the caret position and
     106             :     // inserting message headers at newlines. A trailing newline is ignored.
     107      482614 :     for (std::string::const_iterator it = msg.begin(); it != msg.end(); )
     108             :     {
     109      478369 :       if (*it != '\n')
     110             :       {
     111      470845 :         result << *it++;
     112      470845 :         ++caret_pos();
     113             :       }
     114             :       else
     115             :       {
     116        7524 :         if (++it != msg.end())
     117             :         {
     118        3398 :           result << "\n" << start_of_line.str();
     119        3398 :           caret_pos() = 0;
     120        3398 :           last_caret_pos() = 0;
     121             :         }
     122             :       }
     123             :     }
     124             : 
     125             :     // Pad message with spaces when overwriting a previous line
     126        4245 :     if (msg_ends_with_newline && overwrite && caret_pos() < last_caret_pos())
     127             :     {
     128           0 :       for (std::size_t i = 0; i < last_caret_pos() - caret_pos(); ++i)
     129             :       {
     130           0 :         result << ' ';
     131             :       }
     132             :     }
     133             : 
     134             :     // If this is a finished status message, remember the caret position
     135             :     // so the next line can overwrite properly. If this is a finished message
     136             :     // of another type, restore the trailing newline.
     137        4245 :     if(msg_ends_with_newline)
     138             :     {
     139        4126 :       if (level == status)
     140             :       {
     141           0 :         last_caret_pos() = caret_pos().load();
     142             :       }
     143             :       else
     144             :       {
     145        4126 :         result << "\n";
     146             :       }
     147        4126 :       caret_pos() = 0;
     148             :     }
     149             : 
     150             :     // Store information about this message so next time we can determine
     151             :     // whether we should overwrite the last line or not.
     152        4245 :     last_message_ended_with_newline() = msg_ends_with_newline;
     153        4245 :     if (level == status)
     154             :     {
     155          18 :       last_message_was_status() = msg != "\n";
     156             :     }
     157             :     else
     158             :     {
     159        4227 :       last_message_was_status() = false;
     160             :     }
     161             : 
     162        8490 :     return result.str();
     163        4245 :   }
     164             : 
     165             :   } // namespace log
     166             : } // namespace mcrl2

Generated by: LCOV version 1.14