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