summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/common/Logger.cpp200
-rw-r--r--src/core/common/Logger.hpp490
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 &currentFile() const;
+
+ /**
+ * Returns the current filename or an empty string if no surch file is
+ * available.
+ */
+ const std::string &currentFilename() 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();
};
}