diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/common/Logger.cpp | 200 | ||||
-rw-r--r-- | src/core/common/Logger.hpp | 490 |
2 files changed, 453 insertions, 237 deletions
diff --git a/src/core/common/Logger.cpp b/src/core/common/Logger.cpp index d8cf5b4..b2c724f 100644 --- a/src/core/common/Logger.cpp +++ b/src/core/common/Logger.cpp @@ -25,33 +25,27 @@ namespace ousia { /* Class Logger */ -void Logger::log(Severity severity, std::string msg, TextCursor::Position pos, - TextCursor::Context ctx) +void Logger::log(Severity severity, const std::string &msg, + const SourceLocation &loc) { - // Update the maximum encountered severity level - if (static_cast<int>(severity) > static_cast<int>(maxEncounteredSeverity)) { - maxEncounteredSeverity = severity; - } - - // Only process the message if its severity is larger than the - // set minimum severity. - if (static_cast<int>(severity) >= static_cast<int>(minSeverity)) { - processMessage( - Message{severity, std::move(msg), std::move(pos), std::move(ctx)}); + // Assemble the message and pass it through the filter, then process it + Message message { severity, std::move(msg), loc }; + if (filterMessage(message)) { + processMessage(message); } } -LoggerFork Logger::fork() { return LoggerFork{this, minSeverity}; } +LoggerFork Logger::fork() { return LoggerFork(this); } /* Class LoggerFork */ -void LoggerFork::processMessage(Message msg) +void LoggerFork::processMessage(const Message &msg) { calls.push_back(Call(CallType::MESSAGE, messages.size())); messages.push_back(msg); } -void LoggerFork::processPushFile(File file) +void LoggerFork::processPushFile(const File &file) { calls.push_back(Call(CallType::PUSH_FILE, files.size())); files.push_back(file); @@ -62,25 +56,139 @@ void LoggerFork::processPopFile() calls.push_back(Call(CallType::POP_FILE, 0)); } +void LoggerFork::processSetDefaultLocation(const SourceLocation &loc) +{ + // Check whether setDefaultLocation was called immediately before, if yes, + // simply override the data + if (!calls.empty() && calls.back().type == CallType::SET_DEFAULT_LOCATION) { + locations.back() = loc; + } else { + calls.push_back(Call(CallType::SET_DEFAULT_LOCATION, locations.size())); + locations.push_back(loc); + } +} + +void LoggerFork::purge() +{ + calls.clear(); + messages.clear(); + files.clear(); + locations.clear(); +} + void LoggerFork::commit() { for (const Call &call : calls) { switch (call.type) { case CallType::MESSAGE: { - const Message &msg = messages[call.dataIdx]; - parent->log(msg.severity, msg.msg, msg.pos, msg.ctx); + if (parent->filterMessage(messages[call.dataIdx])) { + parent->processMessage(messages[call.dataIdx]); + } break; } case CallType::PUSH_FILE: { - const File &file = files[call.dataIdx]; - parent->pushFile(file.file, file.pos, file.ctx); + parent->processPushFile(files[call.dataIdx]); break; } case CallType::POP_FILE: - parent->popFile(); + parent->processPopFile(); break; + case CallType::SET_DEFAULT_LOCATION: + parent->processSetDefaultLocation(locations[call.dataIdx]); + break; + } + } + purge(); +} + +/* Class ConcreteLogger */ + +static const Logger::File EMPTY_FILE{"", SourceLocation{}, nullptr, nullptr}; + +void ConcreteLogger::processPushFile(const File &file) +{ + files.push_back(file); +} + +void ConcreteLogger::processPopFile() { files.pop_back(); } + +bool ConcreteLogger::filterMessage(const Message &msg) +{ + // Increment the message count for this severity + uint8_t sev = static_cast<uint8_t>(msg.severity); + if (sev >= messageCounts.size()) { + messageCounts.resize(sev + 1); + } + messageCounts[sev]++; + + // Filter messages with too small severity + return sev >= static_cast<uint8_t>(minSeverity); +} + +void ConcreteLogger::processSetDefaultLocation(const SourceLocation &loc) +{ + defaultLocation = loc; +} + +const Logger::File &ConcreteLogger::currentFile() const +{ + if (!files.empty()) { + return files.back(); + } + return EMPTY_FILE; +} + +const std::string &ConcreteLogger::currentFilename() const +{ + return currentFile().file; +} + +const SourceLocation &ConcreteLogger::messageLocation(const Message &msg) const +{ + if (msg.loc.valid()) { + return msg.loc; + } + return defaultLocation; +} + +SourceContext ConcreteLogger::messageContext(const Message &msg) const +{ + const Logger::File &file = currentFile(); + if (file.ctxCallback) { + return file.ctxCallback(messageLocation(msg), file.ctxCallbackData); + } + return SourceContext{}; +} + +Severity ConcreteLogger::getMaxEncounteredSeverity() +{ + for (ssize_t i = messageCounts.size() - 1; i >= 0; i--) { + if (messageCounts[i] > 0) { + return static_cast<Severity>(i); } } + return Severity::DEBUG; +} + +size_t ConcreteLogger::getSeverityCount(Severity severity) +{ + uint8_t sev = static_cast<uint8_t>(severity); + if (sev >= messageCounts.size()) { + return 0; + } + return messageCounts[sev]; +} + +void ConcreteLogger::reset() +{ + files.clear(); + messageCounts.clear(); +} + +bool ConcreteLogger::hasError() +{ + return getSeverityCount(Severity::ERROR) > 0 || + getSeverityCount(Severity::FATAL_ERROR) > 0; } /* Class Terminal */ @@ -200,38 +308,34 @@ public: /* Class TerminalLogger */ -std::string TerminalLogger::currentFilename() -{ - if (!files.empty()) { - return files.top().file; - } - return std::string{}; -} - -void TerminalLogger::processMessage(Message msg) +void TerminalLogger::processMessage(const Message &msg) { Terminal t(useColor); + // Fetch filename, position and context + const std::string filename = currentFilename(); + const SourceLocation pos = messageLocation(msg); + const SourceContext ctx = messageContext(msg); + // Print the file name - std::string filename = currentFilename(); bool hasFile = !filename.empty(); if (hasFile) { os << t.bright() << filename << t.reset(); } // Print line and column number - if (msg.pos.hasLine()) { + if (pos.hasLine()) { if (hasFile) { os << ':'; } - os << t.bright() << msg.pos.line << t.reset(); - if (msg.pos.hasColumn()) { - os << ':' << msg.pos.column; + os << t.bright() << pos.line << t.reset(); + if (pos.hasColumn()) { + os << ':' << pos.column; } } // Print the optional seperator - if (hasFile || msg.pos.hasLine()) { + if (hasFile || pos.hasLine()) { os << ": "; } @@ -258,26 +362,30 @@ void TerminalLogger::processMessage(Message msg) os << msg.msg << std::endl; // Print the error message context if available - if (msg.ctx.valid()) { - size_t relPos = msg.ctx.relPos; - if (msg.ctx.truncatedStart) { + if (ctx.valid()) { + size_t relPos = ctx.relPos; + if (ctx.truncatedStart) { os << "[...] "; - relPos += 6; } - os << msg.ctx.text; - if (msg.ctx.truncatedEnd) { + os << ctx.text; + if (ctx.truncatedEnd) { os << " [...]"; } os << std::endl; + + if (ctx.truncatedStart) { + os << " "; + } + for (size_t i = 0; i < relPos; i++) { - os << ' '; + if (i < ctx.text.size() && ctx.text[i] == '\t') { + os << '\t'; + } else { + os << ' '; + } } os << t.color(Terminal::GREEN) << '^' << t.reset() << std::endl; } } - -void TerminalLogger::processPushFile(File file) { files.push(file); } - -void TerminalLogger::processPopFile() { files.pop(); } } diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp index eb21eb7..5b58fe2 100644 --- a/src/core/common/Logger.hpp +++ b/src/core/common/Logger.hpp @@ -29,20 +29,20 @@ #ifndef _OUSIA_LOGGER_HPP_ #define _OUSIA_LOGGER_HPP_ +#include <cstdint> #include <ostream> -#include <stack> #include <string> #include <vector> #include "Exceptions.hpp" -#include "TextCursor.hpp" +#include "Location.hpp" namespace ousia { /** * Enum containing the severities used for logging errors and debug messages. */ -enum class Severity : int { +enum class Severity : uint8_t { /** * Indicates that this message was only printed for debugging. Note that * in release builds messages with this severity are discarded. @@ -73,12 +73,6 @@ enum class Severity : int { FATAL_ERROR = 4 }; -#ifdef NDEBUG -static constexpr Severity DEFAULT_MIN_SEVERITY = Severity::NOTE; -#else -static constexpr Severity DEFAULT_MIN_SEVERITY = Severity::DEBUG; -#endif - // Forward declaration class LoggerFork; @@ -93,36 +87,49 @@ class LoggerFork; */ class Logger { public: + friend LoggerFork; + /** - * Describes an included file. + * Describes a file inclusion. */ struct File { /** - * Is the name of the file. + * Current filename. */ std::string file; /** - * Position at which the file was included. + * Location at which the file was included. */ - TextCursor::Position pos; + SourceLocation loc; /** - * Context in which the file was included. + * Callback used to retrieve the context for a certain location */ - TextCursor::Context ctx; + SourceContextCallback ctxCallback; /** - * Constructor of the File struct. + * Data to be passed to the callback. + */ + void *ctxCallbackData; + + /** + * Constructor of the Scope struct. * - * @param file is the name of the included file. - * @param pos is the position in the parent file, at which this file - * was included. - * @param ctx is the context in which the feil was included. + * @param type is the type of + * @param file is the name of the current file. + * @param loc is the location at which the file was included. + * @param ctxCallback is the callback function that should be called + * for looking up the context belonging to a SourceLocation instance. + * @param ctxCallbackData is additional data that should be passed to + * the callback function. */ - File(std::string file, TextCursor::Position pos, - TextCursor::Context ctx) - : file(file), pos(pos), ctx(ctx) + File(std::string file, SourceLocation loc, + SourceContextCallback ctxCallback, void *ctxCallbackData) + : file(std::move(file)), + loc(loc), + ctxCallback(ctxCallback), + ctxCallbackData(ctxCallbackData) { } }; @@ -143,43 +150,22 @@ public: std::string msg; /** - * Position in the text the message refers to. - */ - TextCursor::Position pos; - - /** - * Context the message refers to. + * Location passed along with the message. */ - TextCursor::Context ctx; + SourceLocation loc; /** * Constructor of the Message struct. * * @param severity describes the message severity. * @param msg contains the actual message. - * @param line is the line in the above file the message refers to. - * @param column is the column in the above file the message refers to. */ - Message(Severity severity, std::string msg, TextCursor::Position pos, - TextCursor::Context ctx) - : severity(severity), - msg(std::move(msg)), - pos(std::move(pos)), - ctx(std::move(ctx)){}; + Message(Severity severity, std::string msg, const SourceLocation &loc) + : severity(severity), msg(std::move(msg)), loc(loc){}; }; protected: /** - * Minimum severity a log message should have before it is discarded. - */ - const Severity minSeverity; - - /** - * Maximum encountered log message severity. - */ - Severity maxEncounteredSeverity; - - /** * Function to be overriden by child classes to actually display or store * the messages. The default implementation just discards all incomming * messages. @@ -187,37 +173,46 @@ protected: * @param msg is an instance of the Message struct containing the data that * should be logged. */ - virtual void processMessage(Message msg) {} + virtual void processMessage(const Message &msg) {} + + /** + * Called right before the processMessage function is called. Allows any + * concrete implementation of the Logger class to discard certain messages. + * + * @param msg is the message that should be filtered. + * @return true if the message should be passed to the processMessage + * method, false otherwise. + */ + virtual bool filterMessage(const Message &msg) { return true; } /** * Called whenever a new file is pushed onto the stack. * - * @param file is the file that should be pushed onto the stack. + * @param file is the file structure that should be stored on the stack. */ - virtual void processPushFile(File file) {} + virtual void processPushFile(const File &file) {} /** - * Called whenever a file is popped from the stack. + * Called whenever a scope is popped from the stack. */ virtual void processPopFile() {} -public: /** - * Constructor of the Logger class. + * Called whenever the setDefaultLocation function is called. * - * @param minSeverity is the minimum severity a log message should have. - * Messages below this severity are discarded. + * @param loc is the default location that should be set. */ - Logger(Severity minSeverity = DEFAULT_MIN_SEVERITY) - : minSeverity(minSeverity), maxEncounteredSeverity(Severity::DEBUG) - { - } + virtual void processSetDefaultLocation(const SourceLocation &loc) {} +public: /** * Virtual destructor. */ virtual ~Logger(){}; + // Default constructor + Logger() {} + // No copy Logger(const Logger &) = delete; @@ -230,12 +225,10 @@ public: * * @param severity is the severity of the log message. * @param msg is the actual log message. - * @param pos is the position the log message refers to. - * @param ctx describes the context of the log message. + * @param loc is the location in the source file the message refers to. */ - void log(Severity severity, std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}); + void log(Severity severity, const std::string &msg, + const SourceLocation &loc = SourceLocation{}); /** * Logs the given loggable exception. @@ -244,7 +237,7 @@ public: */ void log(const LoggableException &ex) { - log(Severity::ERROR, ex.msg, ex.getPosition(), ex.getContext()); + log(Severity::ERROR, ex.msg, ex.getLocation()); } /** @@ -253,13 +246,13 @@ public: * * @param severity is the severity of the log message. * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides location + * information. */ - template <class PosType> - void log(Severity severity, std::string msg, PosType &pos) + template <class LocationType> + void log(Severity severity, const std::string &msg, LocationType &loc) { - log(severity, std::move(msg), pos.getPosition(), pos.getContext()); + log(severity, msg, loc.getLocation()); } /** @@ -267,15 +260,13 @@ public: * is compiled in the release mode (with the NDEBUG flag). * * @param msg is the actual log message. - * @param pos describes the position of the debug message. - * @param ctx describes the context of the debug message. + * @param loc is the location in the source file the message refers to. */ - void debug(std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void debug(const std::string &msg, + const SourceLocation &loc = SourceLocation{}) { #ifndef NDEBUG - log(Severity::DEBUG, std::move(msg), std::move(pos), std::move(ctx)); + log(Severity::DEBUG, msg, loc); #endif } @@ -284,14 +275,14 @@ public: * is compiled in the release mode. * * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides position + * information. */ - template <class PosType> - void debug(std::string msg, PosType &pos) + template <class LocationType> + void debug(const std::string &msg, LocationType &loc) { #ifndef NDEBUG - log(Severity::DEBUG, std::move(msg), pos); + log(Severity::DEBUG, msg, loc); #endif } @@ -299,167 +290,162 @@ public: * Logs a note. * * @param msg is the actual log message. - * @param pos describes the position of the note. - * @param ctx describes the context of the note. + * @param loc is the location in the source file the message refers to. */ - void note(std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void note(const std::string &msg, + const SourceLocation &loc = SourceLocation{}) { - log(Severity::NOTE, std::move(msg), std::move(pos), std::move(ctx)); + log(Severity::NOTE, msg, loc); } /** * Logs a note. * * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides position + * information. */ - template <class PosType> - void note(std::string msg, PosType &pos) + template <class LocationType> + void note(const std::string &msg, LocationType &loc) { - log(Severity::NOTE, std::move(msg), pos); + log(Severity::NOTE, msg, loc); } /** * Logs a warning. * * @param msg is the actual log message. - * @param pos describes the position of the warning. - * @param ctx describes the context of the warning. + * @param loc is a reference to a variable which provides position */ - void warning(std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void warning(const std::string &msg, + const SourceLocation &loc = SourceLocation{}) { - log(Severity::WARNING, std::move(msg), std::move(pos), std::move(ctx)); + log(Severity::WARNING, msg, loc); } /** * Logs a warning. * * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides position + * information. */ - template <class PosType> - void warning(std::string msg, PosType &pos) + template <class LocationType> + void warning(const std::string &msg, LocationType &loc) { - log(Severity::WARNING, std::move(msg), pos); + log(Severity::WARNING, msg, loc); } /** * Logs an error message. * * @param msg is the actual log message. - * @param pos is the position at which the error occured. - * @param ctx describes the context in which the error occured. + * @param loc is a reference to a variable which provides position */ - void error(std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void error(const std::string &msg, + const SourceLocation &loc = SourceLocation{}) { - log(Severity::ERROR, std::move(msg), std::move(pos), std::move(ctx)); + log(Severity::ERROR, msg, std::move(loc)); } /** * Logs an error message. * * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides position + * information. */ - template <class PosType> - void error(std::string msg, PosType &pos) + template <class LocationType> + void error(const std::string &msg, LocationType &loc) { - log(Severity::ERROR, std::move(msg), pos); + log(Severity::ERROR, msg, loc); } /** * Logs a fatal error message. * * @param msg is the actual log message. - * @param pos is the position at which the error occured. - * @param ctx describes the context in which the error occured. + * @param loc is a reference to a variable which provides position */ - void fatalError(std::string msg, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void fatalError(const std::string &msg, + const SourceLocation &loc = SourceLocation{}) { - log(Severity::FATAL_ERROR, std::move(msg), std::move(pos), - std::move(ctx)); + log(Severity::FATAL_ERROR, msg, loc); } /** * Logs a fatal error message. * * @param msg is the actual log message. - * @param pos is a reference to a variable which provides position and - * context information. + * @param loc is a reference to a variable which provides position + * information. */ - template <class PosType> - void fatalError(std::string msg, PosType &pos) + template <class LocationType> + void fatalError(const std::string &msg, LocationType &loc) { - log(Severity::FATAL_ERROR, std::move(msg), pos); + log(Severity::FATAL_ERROR, msg, loc); } /** * Pushes a new file name onto the internal filename stack. * * @param name is the name of the file to be added to the stack. - * @param pos is the position from which the new file is included. - * @param ctx is the context in which the new file is included. + * @param loc is the position from which the new file is included. */ - void pushFile(std::string name, - TextCursor::Position pos = TextCursor::Position{}, - TextCursor::Context ctx = TextCursor::Context{}) + void pushFile(std::string name, SourceLocation loc = SourceLocation{}, + SourceContextCallback contextCallback = nullptr, + void *contextCallbackData = nullptr) { - processPushFile(File(std::move(name), std::move(pos), std::move(ctx))); + processPushFile( + File(std::move(name), loc, contextCallback, contextCallbackData)); } /** - * Pops the filename from the internal filename stack. - * - * @return the current size of the filename stack. + * Pops the filename from the internal filename stack. Resets any location + * set by the setDefaultLocation() method. */ - void popFile() { processPopFile(); } + void popFile() + { + processPopFile(); + resetDefaultLocation(); + } /** - * Returns the maximum severity that was encountered by the Logger but at - * least Severity::DEBUG. + * Sets the default location. The default location is automatically reset + * once the popFile() method is called. * - * @return the severity of the most severe log message but at least - * Severity::DEBUG. - */ - Severity getMaxEncounteredSeverity() { return maxEncounteredSeverity; } - - /** - * Resets the maximum encountered severity to the debug level. + * @param loc is the location that should be used if no (valid) location is + * specified in the Logger. */ - void resetMaxEncounteredSeverity() + void setDefaultLocation(const SourceLocation &loc) { - maxEncounteredSeverity = Severity::DEBUG; + processSetDefaultLocation(loc); } /** - * Returns the minimum severity. Messages with a smaller severity are - * discarded. - * - * @return the minimum severity. + * Resets the default location, a previously set default location will be + * no longer used. */ - Severity getMinSeverity() { return minSeverity; } + void resetDefaultLocation() { processSetDefaultLocation(SourceLocation{}); } /** * Returns a forked logger instance which can be used to collect log * messages for which it is not sure whether they will be used. + * + * @return a LoggerFork instance which buffers all method calls and commits + * them once the "commit()" method is called. */ LoggerFork fork(); }; /** * Fork of the Logger -- stores all logged messages without actually pushing - * them to the underlying logger instance. + * them to the underlying logger instance. Maintains its own + * maxEncounteredSeverity independently from the parent Logger instance. + * Internally the LoggerFork class records all calls to the internal + * processMessage, processPushScope and processPopFile calls and replays these + * calls in the exact order on the parent Logger instance once the commit + * function is called. */ class LoggerFork : public Logger { private: @@ -468,7 +454,7 @@ private: /** * Intanally used to store the incomming function calls. */ - enum class CallType { MESSAGE, PUSH_FILE, POP_FILE }; + enum class CallType { MESSAGE, PUSH_FILE, POP_FILE, SET_DEFAULT_LOCATION }; /** * Datastructure used to represent a logger function call. @@ -505,11 +491,16 @@ private: std::vector<Message> messages; /** - * Vector storing all incomming pushed files. + * Vector storing all incomming pushed Scope instances. */ std::vector<File> files; /** + * Vector storing all incomming location instances. + */ + std::vector<SourceLocation> locations; + + /** * Parent logger instance. */ Logger *parent; @@ -517,44 +508,178 @@ private: /** * Constructor of the LoggerFork class. * - * @param minSeverity is the minimum severity a message should have to be - * stored. * @param parent is the parent logger instance. */ - LoggerFork(Logger *parent, Severity minSeverity) - : Logger(minSeverity), parent(parent) - { - } + LoggerFork(Logger *parent) : parent(parent) {} protected: - void processMessage(Message msg) override; - void processPushFile(File file) override; + void processMessage(const Message &msg) override; + void processPushFile(const File &file) override; void processPopFile() override; + void processSetDefaultLocation(const SourceLocation &loc) override; public: + // Default move constructor + LoggerFork(LoggerFork &&l) + : calls(std::move(l.calls)), + messages(std::move(l.messages)), + files(std::move(l.files)), + locations(std::move(l.locations)), + parent(std::move(l.parent)){}; + /** * Commits all collected messages to the parent Logger instance. */ void commit(); /** - * Explicitly declared move constructor. + * Purges all collected messages. Resets the LoggerFork to its initial + * state (except for the maximum encountered severity). */ - LoggerFork(LoggerFork &&l) - : Logger(l.getMinSeverity()), - calls(std::move(l.calls)), - messages(std::move(l.messages)), - files(std::move(l.files)), - parent(std::move(l.parent)) + void purge(); +}; + +#ifdef NDEBUG +static constexpr Severity DEFAULT_MIN_SEVERITY = Severity::NOTE; +#else +static constexpr Severity DEFAULT_MIN_SEVERITY = Severity::DEBUG; +#endif + +/** + * The ConcreteLogger class contains data fields used to specify the minimum + * severity and to gather statistics about encountered log messages. + * Additionally it provides the File stack and helper functions that can be + * used to access location and context of a given message. + */ +class ConcreteLogger : public Logger { +private: + /** + * Stack containing the current file instance. + */ + std::vector<File> files; + + /** + * Vector used to store the counts of each message type. + */ + std::vector<size_t> messageCounts; + + /** + * Minimum severity to be used for filtering messages. + */ + Severity minSeverity; + + /** + * Current default location. + */ + SourceLocation defaultLocation; + +protected: + /** + * Filters the messages according to the given minimum severity. + * + * @param msg is the message that should be filtered. + * @return true if the message has a higher or equal severity compared to + * the minimum severity. + */ + bool filterMessage(const Message &msg) override; + + /** + * Pushes the given file descriptor onto the internal file stack. + * + * @param file is the File descriptor to be pushed onto the internal file + * stack. + */ + void processPushFile(const File &file) override; + + /** + * Pops the given file descriptor from the internal file stack. + */ + void processPopFile() override; + + /** + * Sets the default location. + * + * @param loc is the new default location. + */ + void processSetDefaultLocation(const SourceLocation &loc) override; + +public: + /** + * Creates a ConcreteLogger instance with the given minimum severity. + * + * @param minSeverity is the severity below which message should be + * discarded. + */ + ConcreteLogger(Severity minSeverity = DEFAULT_MIN_SEVERITY) + : minSeverity(minSeverity) { } + + /** + * Returns the name of the current file or an empty instance of the File + * instance if no current file is available. + * + * @return the name of the current file. + */ + const File ¤tFile() const; + + /** + * Returns the current filename or an empty string if no surch file is + * available. + */ + const std::string ¤tFilename() const; + + /** + * Returns the current cursor location. + * + * @return the current cursor location. + */ + const SourceLocation &messageLocation(const Message &msg) const; + + /** + * Returns the current cursor context. + * + * @return the current cursor context. + */ + SourceContext messageContext(const Message &msg) const; + + /** + * Returns the maximum encountered severity. + * + * @return the maximum encountered severity. + */ + Severity getMaxEncounteredSeverity(); + + /** + * Returns the number of messages for the given severity. + * + * @param severity is the log severity for which the message count should + * be returned. + * @return the number of messages for this severity. Returns zero for + * invalid arguments. + */ + size_t getSeverityCount(Severity severity); + + /** + * Resets the statistics gathered by the ConcreteLogger instance (the number + * of messages per log severity) and the internal file stack. + */ + void reset(); + + /** + * Returns true if at least one message with either a fatal error or error + * severity was logged. + * + * @return true if an error or fatal error was logged. + */ + bool hasError(); }; /** * Class extending the Logger class and printing the log messages to the given * stream. */ -class TerminalLogger : public Logger { +class TerminalLogger : public ConcreteLogger { private: /** * Reference to the target output stream. @@ -567,20 +692,8 @@ private: */ bool useColor; - /** - * Stack used to keep the file references. - */ - std::stack<File> files; - - /** - * The size of the stack the last time a file backtrace was printed. - */ - size_t lastFilePrinted = 0; - protected: - void processMessage(Message msg) override; - void processPushFile(File file) override; - void processPopFile() override; + void processMessage(const Message &msg) override; public: /** @@ -595,14 +708,9 @@ public: */ TerminalLogger(std::ostream &os, bool useColor = false, Severity minSeverity = DEFAULT_MIN_SEVERITY) - : Logger(minSeverity), os(os), useColor(useColor) + : ConcreteLogger(minSeverity), os(os), useColor(useColor) { } - - /** - * Returns the name of the topmost file. - */ - std::string currentFilename(); }; } |