mCRL2
Loading...
Searching...
No Matches
logger.cpp
Go to the documentation of this file.
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 <array>
13#include <cassert>
14
15
16namespace mcrl2::log {
17
18 std::string format_time(const time_t* t)
19 {
20 struct tm* r;
21 r = localtime(t);
22
23 std::array<char, 11> buffer{};
24 std::size_t res = strftime(buffer.data(), buffer.size(), "%H:%M:%S", r);
25 if(res == 0)
26 {
27 std::clog << "Could not write time to buffer" << std::endl;
28 return std::string();
29 }
30 return buffer.data();
31 }
32
33 std::string formatter::format(const log_level_t level,
34 const time_t timestamp,
35 const std::string& msg,
36 const bool print_time_information)
37 {
38 assert(log_level_t::quiet != level);
39 // Construct the message header, with or without time and debug level info.
40 const bool print_log_level= level >= log_level_t::debug;
41 std::stringstream start_of_line;
42 if (print_time_information || print_log_level)
43 {
44 start_of_line << "[";
45 }
46 if (print_time_information)
47 {
48 start_of_line << format_time(&timestamp);
49 }
50 if (print_time_information && print_log_level)
51 {
52 start_of_line << " ";
53 }
54 if (print_log_level)
55 {
56 start_of_line << log_level_to_string(level);
57 }
58 if (print_time_information || print_log_level)
59 {
60 start_of_line << "] ";
61 }
62 if (print_log_level)
63 {
64 start_of_line << std::string(7 - log_level_to_string(level).size(), ' ');
65 }
66
67 // Check if message is finished. We
68 bool msg_ends_with_newline = false;
69 if (msg.size() > 0)
70 {
71 msg_ends_with_newline = (msg[msg.size()-1] == '\n');
72 }
73
74 std::stringstream result;
75
76 // Determine whether the last line should be overwritten (by inserting a
77 // carriage return).
78 bool overwrite = false;
80 {
81 if (level == log_level_t::status)
82 {
84 {
85 if (msg != "\n")
86 {
87 result << "\r" << start_of_line.str();
88 overwrite = true;
89 }
90 else
91 {
92 result << "\n";
93 }
94 }
95 }
96 else
97 {
98 result << "\n" << start_of_line.str();
99 }
100 }
101 else
103 {
104 result << start_of_line.str();
105 }
106
107 // Copy the message to result, keeping track of the caret position and
108 // inserting message headers at newlines. A trailing newline is ignored.
109 for (std::string::const_iterator it = msg.begin(); it != msg.end(); )
110 {
111 if (*it != '\n')
112 {
113 result << *it++;
114 ++caret_pos();
115 }
116 else
117 {
118 if (++it != msg.end())
119 {
120 result << "\n" << start_of_line.str();
121 caret_pos() = 0;
122 last_caret_pos() = 0;
123 }
124 }
125 }
126
127 // Pad message with spaces when overwriting a previous line
128 if (msg_ends_with_newline && overwrite && caret_pos() < last_caret_pos())
129 {
130 for (std::size_t i = 0; i < last_caret_pos() - caret_pos(); ++i)
131 {
132 result << ' ';
133 }
134 }
135
136 // If this is a finished status message, remember the caret position
137 // so the next line can overwrite properly. If this is a finished message
138 // of another type, restore the trailing newline.
139 if(msg_ends_with_newline)
140 {
141 if (level == log_level_t::status)
142 {
144 }
145 else
146 {
147 result << "\n";
148 }
149 caret_pos() = 0;
150 }
151
152 // Store information about this message so next time we can determine
153 // whether we should overwrite the last line or not.
154 last_message_ended_with_newline() = msg_ends_with_newline;
155 if (level == log_level_t::status)
156 {
157 last_message_was_status() = msg != "\n";
158 }
159 else
160 {
162 }
163
164 return result.str();
165 }
166
167} // namespace mcrl2::log
Mixin that takes care of formatting of a message.
Definition logger.h:284
static std::atomic< std::size_t > & caret_pos()
Definition logger.h:303
static std::atomic< bool > & last_message_ended_with_newline()
Records whether the last message that was printed ended with a new line.
Definition logger.h:289
static std::atomic< std::size_t > & last_caret_pos()
Definition logger.h:310
static std::atomic< bool > & last_message_was_status()
Definition logger.h:296
std::string format_time(const time_t *t)
Definition logger.cpp:18
log_level_t
Log levels that are supported.
Definition logger.h:31
std::size_t operator()(const std::vector< X > &v) const