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(×tamp); 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