LCOV - code coverage report
Current view: top level - utilities/source - logger.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 46 62 74.2 %
Date: 2020-02-29 00:53:40 Functions: 3 4 75.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        4137 :   std::string formatter::format(const log_level_t level, 
      33             :                                 const std::string& hint, 
      34             :                                 const time_t timestamp, 
      35             :                                 const std::string& msg,
      36             :                                 const bool print_time_information)
      37             :   {
      38             :     // Construct the message header, with or without time and debug level info.
      39        4137 :     const log_level_t default_level=logger::get_reporting_level(hint);
      40        4137 :     const bool print_log_level= level==error || level > verbose || default_level>=debug;
      41        8274 :     std::stringstream start_of_line;
      42        4137 :     if (print_time_information || print_log_level)
      43             :     {
      44        3763 :       start_of_line << "[";
      45             :     }
      46        4137 :     if (print_time_information)
      47             :     {
      48           0 :       start_of_line << format_time(&timestamp);
      49             :     }
      50        4137 :     if (print_time_information && print_log_level)
      51             :     {
      52           0 :       start_of_line << " ";
      53             :     }
      54        4137 :     if (print_log_level)
      55             :     {
      56             :       start_of_line << hint
      57        7526 :                     << (hint == std::string()?"":"::")
      58        7526 :                     << log_level_to_string(level);
      59             :     }
      60        4137 :     if (print_time_information || print_log_level)
      61             :     {
      62        3763 :       start_of_line << "] ";
      63             :     }
      64        4137 :     if (print_log_level)
      65             :     {
      66        3763 :       start_of_line << std::string(7 - log_level_to_string(level).size(), ' ');
      67             :     }
      68             : 
      69             :     // Check if message is finished. We
      70        4137 :     bool msg_ends_with_newline = false;
      71        4137 :     if (msg.size() > 0)
      72             :     {
      73        4119 :       msg_ends_with_newline = (msg[msg.size()-1] == '\n');
      74             :     }
      75             : 
      76        8274 :     std::stringstream result;
      77             : 
      78             :     // Determine whether the last line should be overwritten (by inserting a
      79             :     // carriage return).
      80        4137 :     bool overwrite = false;
      81        4137 :     if (last_message_was_status())
      82             :     {
      83          18 :       if (level == status && hint == last_hint())
      84             :       {
      85          12 :         if (last_message_ended_with_newline())
      86             :         {
      87           0 :           if (msg != "\n")
      88             :           {
      89           0 :             result << "\r" << start_of_line.str();
      90           0 :             overwrite = true;
      91             :           }
      92             :           else
      93             :           {
      94           0 :             result << "\n";
      95             :           }
      96             :         }
      97             :       }
      98             :       else
      99             :       {
     100           6 :         result << "\n" << start_of_line.str();
     101             :       }
     102             :     }
     103             :     else
     104        4119 :     if (last_message_ended_with_newline())
     105             :     {
     106        4028 :       result << start_of_line.str();
     107             :     }
     108             : 
     109             :     // Copy the message to result, keeping track of the caret position and
     110             :     // inserting message headers at newlines. A trailing newline is ignored.
     111      473956 :     for (std::string::const_iterator it = msg.begin(); it != msg.end(); )
     112             :     {
     113      469819 :       if (*it != '\n')
     114             :       {
     115      462403 :         result << *it++;
     116      462403 :         ++caret_pos();
     117             :       }
     118             :       else
     119             :       {
     120        7416 :         if (++it != msg.end())
     121             :         {
     122        3388 :           result << "\n" << start_of_line.str();
     123        3388 :           caret_pos() = 0;
     124        3388 :           last_caret_pos() = 0;
     125             :         }
     126             :       }
     127             :     }
     128             : 
     129             :     // Pad message with spaces when overwriting a previous line
     130        4137 :     if (msg_ends_with_newline && overwrite && caret_pos() < last_caret_pos())
     131             :     {
     132           0 :       for (std::size_t i = 0; i < last_caret_pos() - caret_pos(); ++i)
     133             :       {
     134           0 :         result << ' ';
     135             :       }
     136             :     }
     137             : 
     138             :     // If this is a finished status message, remember the caret position
     139             :     // so the next line can overwrite properly. If this is a finished message
     140             :     // of another type, restore the trailing newline.
     141        4137 :     if(msg_ends_with_newline)
     142             :     {
     143        4028 :       if (level == status)
     144             :       {
     145           0 :         last_caret_pos() = caret_pos();
     146             :       }
     147             :       else
     148             :       {
     149        4028 :         result << "\n";
     150             :       }
     151        4028 :       caret_pos() = 0;
     152             :     }
     153             : 
     154             :     // Store information about this message so next time we can determine
     155             :     // whether we should overwrite the last line or not.
     156        4137 :     last_message_ended_with_newline() = msg_ends_with_newline;
     157        4137 :     if (level == status)
     158             :     {
     159          18 :       last_message_was_status() = msg != "\n";
     160          18 :       last_hint() = hint;
     161             :     }
     162             :     else
     163             :     {
     164        4119 :       last_message_was_status() = false;
     165             :     }
     166             : 
     167        8274 :     return result.str();
     168             :   }
     169             : 
     170             :   } // namespace log
     171         438 : } // namespace mcrl2

Generated by: LCOV version 1.13