diff options
| author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-11 21:46:11 +0100 | 
|---|---|---|
| committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-11 21:46:11 +0100 | 
| commit | 741463dd18efd8d126bcc70224025703858fdef7 (patch) | |
| tree | 82f83172a3229f14957b6c3f90fd10180c6b2612 | |
| parent | 3f62168ed0b088eec3cb2903f03966f7d501f564 (diff) | |
refactored logger
| -rw-r--r-- | src/core/common/CharReader.cpp | 6 | ||||
| -rw-r--r-- | src/core/common/CharReader.hpp | 86 | ||||
| -rw-r--r-- | src/core/common/Exceptions.cpp | 18 | ||||
| -rw-r--r-- | src/core/common/Exceptions.hpp | 77 | ||||
| -rw-r--r-- | src/core/common/Logger.cpp | 114 | ||||
| -rw-r--r-- | src/core/common/Logger.hpp | 465 | ||||
| -rw-r--r-- | src/core/common/TextCursor.hpp | 168 | ||||
| -rw-r--r-- | src/core/common/VariantReader.cpp | 18 | ||||
| -rw-r--r-- | src/plugins/xml/XmlParser.cpp | 10 | ||||
| -rw-r--r-- | test/core/common/CharReaderTest.cpp | 44 | ||||
| -rw-r--r-- | test/core/common/LoggerTest.cpp | 48 | ||||
| -rw-r--r-- | test/plugins/xml/XmlParserTest.cpp | 2 | 
12 files changed, 557 insertions, 499 deletions
| diff --git a/src/core/common/CharReader.cpp b/src/core/common/CharReader.cpp index 373c0c1..4bd81ed 100644 --- a/src/core/common/CharReader.cpp +++ b/src/core/common/CharReader.cpp @@ -83,7 +83,7 @@ Buffer::Buffer(const std::string &str)  Buffer::~Buffer()  {  	// Make sure all cursors have been deleted -	for (bool cursor_alive: alive) { +	for (bool cursor_alive : alive) {  		assert(!cursor_alive);  	}  } @@ -516,7 +516,7 @@ CharReaderFork CharReader::fork()  	return CharReaderFork(buffer, readCursor, peekCursor, coherent);  } -CharReader::Context CharReader::getContext(ssize_t maxSize) +TextCursor::Context CharReader::getContext(ssize_t maxSize)  {  	// Clone the current read cursor  	Buffer::CursorId cur = buffer->createCursor(readCursor.cursor); @@ -612,7 +612,7 @@ CharReader::Context CharReader::getContext(ssize_t maxSize)  	// Delete the newly created cursor  	buffer->deleteCursor(cur); -	return CharReader::Context{ss.str(), relPos, !foundBegin || tStart != start, +	return TextCursor::Context{ss.str(), relPos, !foundBegin || tStart != start,  	                           !foundEnd || tEnd != end};  } diff --git a/src/core/common/CharReader.hpp b/src/core/common/CharReader.hpp index 3cbe4b4..7be5e08 100644 --- a/src/core/common/CharReader.hpp +++ b/src/core/common/CharReader.hpp @@ -32,6 +32,8 @@  #include <memory>  #include <vector> +#include "TextCursor.hpp" +  namespace ousia {  /** @@ -359,52 +361,6 @@ class CharReaderFork;   * of linebreaks and converts these to a single '\n'.   */  class CharReader { -public: -	/** -	 * The context struct is used to represent the current context the char -	 * reader is in. This context can for example be used when building error -	 * messages. -	 */ -	struct Context { -		/** -		 * Set to the content of the current line. -		 */ -		std::string line; - -		/** -		 * Relative position (in characters) within that line. -		 */ -		size_t relPos; - -		/** -		 * Set to true if the beginning of the line has been truncated (because -		 * the reader position is too far away from the actual position of the -		 * line). -		 */ -		bool truncatedStart; - -		/** -		 * Set to true if the end of the line has been truncated (because the -		 * reader position is too far away from the actual end position of the -		 * line. -		 */ -		bool truncatedEnd; - -		Context() -		    : line(), relPos(0), truncatedStart(false), truncatedEnd(false) -		{ -		} - -		Context(std::string line, size_t relPos, bool truncatedStart, -		        bool truncatedEnd) -		    : line(std::move(line)), -		      relPos(relPos), -		      truncatedStart(truncatedStart), -		      truncatedEnd(truncatedEnd) -		{ -		} -	}; -  protected:  	/**  	 * Internally used cursor structure for managing the read and the peek @@ -419,19 +375,20 @@ protected:  		/**  		 * Current line the cursor is in.  		 */ -		uint32_t line; +		TextCursor::PosType line;  		/**  		 * Current column the cursor is in.  		 */ -		uint32_t column; +		TextCursor::PosType column;  		/**  		 * Constructor of the Cursor class.  		 *  		 * @param cursor is the underlying cursor in the Buffer instance.  		 */ -		Cursor(Buffer::CursorId cursor, size_t line, size_t column) +		Cursor(Buffer::CursorId cursor, TextCursor::PosType line, +		       TextCursor::PosType column)  		    : cursor(cursor), line(line), column(column)  		{  		} @@ -591,31 +548,35 @@ public:  	bool atEnd() const { return buffer->atEnd(readCursor.cursor); }  	/** -	 * Returns the current line (starting with one). -	 * -	 * @return the current line number. +	 * Returns the offset of the read cursor in bytes.  	 */ -	uint32_t getLine() const { return readCursor.line; } +	size_t getOffset() const { return buffer->offset(readCursor.cursor); }  	/** -	 * Returns the current column (starting with one). -	 * -	 * @return the current column number. +	 * Returns the line number the read cursor currently is at.  	 */ -	uint32_t getColumn() const { return readCursor.column; } +	TextCursor::PosType getLine() const { return readCursor.line; }  	/** -	 * Returns the current byte offset of the read cursor. -	 * -	 * @return the byte position within the stream. +	 * Returns the column the read cursor currently is at.  	 */ -	size_t getOffset() const { return buffer->offset(readCursor.cursor); }; +	TextCursor::PosType getColumn() const { return readCursor.column; } + +	/** +	 * Returns the current position of the read cursor (line and column). +	 */ +	TextCursor::Position getPosition() const +	{ +		return TextCursor::Position(getLine(), getColumn(), getOffset()); +	}  	/**  	 * Returns the line the read cursor currently is in, but at most the  	 * given number of characters in the form of a Context structure. +	 * +	 * @param maxSize is the maximum length of the extracted context  	 */ -	Context getContext(ssize_t maxSize); +	TextCursor::Context getContext(ssize_t maxSize = 60);  };  /** @@ -658,7 +619,6 @@ public:  	 */  	void commit();  }; -  }  #endif /* _OUSIA_CHAR_READER_HPP_ */ diff --git a/src/core/common/Exceptions.cpp b/src/core/common/Exceptions.cpp index d064f35..30c5626 100644 --- a/src/core/common/Exceptions.cpp +++ b/src/core/common/Exceptions.cpp @@ -25,21 +25,21 @@ namespace ousia {  /* Class LoggableException */  std::string LoggableException::formatMessage(const std::string &msg, -                                             const std::string &file, -                                             int line, int column) +                                             const TextCursor::Position &pos, +                                             const TextCursor::Context &ctx)  {  	std::stringstream ss;  	ss << "error "; -	if (!file.empty()) { -		ss << "while processing \"" << file << "\" "; -	} -	if (line >= 0) { -		ss << "at line " << line << ", "; -		if (column >= 0) { -			ss << "column " << column << " "; +	if (pos.hasLine()) { +		ss << "at line " << pos.line << ", "; +		if (pos.hasColumn()) { +			ss << "column " << pos.column << " ";  		}  	}  	ss << "with message: " << msg; +	if (ctx.valid()) { +		ss << " in context \"" << ctx.text << "\""; +	}  	return ss.str();  }  } diff --git a/src/core/common/Exceptions.hpp b/src/core/common/Exceptions.hpp index 00d6106..443c176 100644 --- a/src/core/common/Exceptions.hpp +++ b/src/core/common/Exceptions.hpp @@ -27,6 +27,8 @@  #ifndef _OUSIA_EXCEPTIONS_HPP_  #define _OUSIA_EXCEPTIONS_HPP_ +#include "TextCursor.hpp" +  namespace ousia {  /** @@ -81,80 +83,81 @@ private:  	 * reported to the runtime environment.  	 */  	static std::string formatMessage(const std::string &msg, -	                                 const std::string &file, int line, -	                                 int column); +	                                 const TextCursor::Position &pos, +	                                 const TextCursor::Context &ctx);  public:  	/** -	 * Message describing the error that occured. +	 * Reported error message.  	 */  	const std::string msg;  	/** -	 * Name of the file in which the error occured. May be empty. +	 * Position in the document at which the exception occurred.  	 */ -	const std::string file; +	const TextCursor::Position pos;  	/** -	 * Line at which the exception occured. Negative values are ignored. +	 * Context in the document text in which the exception occurred.  	 */ -	const int line; - -	/** -	 * Column at which the exception occured. Negative values are ignored. -	 */ -	const int column; +	const TextCursor::Context ctx;  	/**  	 * Constructor of the LoggableException class.  	 *  	 * @param msg contains the error message. -	 * @param file provides the context the message refers to. May be empty. -	 * @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. +	 * @param pos is the position at which the error occured. +	 * @param ctx describes the context in which the error occured.  	 */ -	LoggableException(std::string msg, std::string file, int line = -1, -	                  int column = -1) -	    : OusiaException(formatMessage(msg, file, line, column)), +	LoggableException(std::string msg, +	                  TextCursor::Position pos = TextCursor::Position{}, +	                  TextCursor::Context ctx = TextCursor::Context{}) +	    : OusiaException(formatMessage(msg, pos, ctx)),  	      msg(std::move(msg)), -	      file(std::move(file)), -	      line(line), -	      column(column) +	      pos(std::move(pos)), +	      ctx(std::move(ctx))  	{  	}  	/** -	 * Constructor of the LoggableException class with empty file. +	 * Constructor of the LoggableException class.  	 *  	 * @param msg contains the error 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. +	 * @param offs is the byte offset.  	 */ -	LoggableException(std::string msg, int line = -1, int column = -1) -	    : OusiaException(formatMessage(msg, "", line, column)), -	      msg(std::move(msg)), -	      line(line), -	      column(column) +	LoggableException(std::string msg, TextCursor::PosType line, +	                  TextCursor::PosType column, size_t offs) +	    : LoggableException(msg, TextCursor::Position(line, column, offs))  	{  	}  	/** -	 * Constructor of the LoggableException class with empty file and an -	 * position object. +	 * Constructor of LoggableException for arbitrary position objects.  	 *  	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @param pos is a reference to a variable with position and context data.  	 */  	template <class PosType> -	LoggableException(std::string msg, const PosType &pos) -	    : OusiaException( -	          formatMessage(msg, "", pos.getLine(), pos.getColumn())), -	      msg(std::move(msg)), -	      line(pos.getLine()), -	      column(pos.getColumn()) +	LoggableException(std::string msg, PosType &pos) +	    : LoggableException(std::move(msg), pos.getPosition(), pos.getContext())  	{  	} + +	/** +	 * Returns the position at which the exception occured in the text. +	 * +	 * @return the position descriptor. +	 */ +	TextCursor::Position getPosition() const { return pos; } + +	/** +	 * Returns the context in which the exception occured in the text. +	 * +	 * @return the context descriptor. +	 */ +	TextCursor::Context getContext() const { return ctx; }  };  } diff --git a/src/core/common/Logger.cpp b/src/core/common/Logger.cpp index 17f55a6..913594f 100644 --- a/src/core/common/Logger.cpp +++ b/src/core/common/Logger.cpp @@ -23,50 +23,8 @@  namespace ousia { -/* Class Logger */ +/* Class Terminal */ -void Logger::log(Severity severity, const std::string &msg, -                 const std::string &file, int line, int column) -{ -	// Copy the current severity level -	if (static_cast<int>(severity) > static_cast<int>(maxEncounteredSeverity)) { -		maxEncounteredSeverity = severity; -	} - -	// Call the actual log message function if the severity is larger or equal -	// to the minimum severity -	if (static_cast<int>(severity) >= static_cast<int>(minSeverity)) { -		process(Message{severity, msg, file, line, column}); -	} -} - -unsigned int Logger::pushFilename(const std::string &name) -{ -	filenameStack.push(name); -	return filenameStack.size(); -} - -unsigned int Logger::popFilename() -{ -	filenameStack.pop(); -	return filenameStack.size(); -} - -void Logger::unwindFilenameStack(unsigned int pos) -{ -	while (filenameStack.size() > pos && !filenameStack.empty()) { -		filenameStack.pop(); -	} -} - -/* Class TerminalLogger */ - -/** - * Small class used internally for formated terminal output using ANSI/VT100 - * escape codes on supported terminals. - * - * TODO: Deactivate if using windows or use the corresponding API function. - */  class Terminal {  private:  	/** @@ -109,29 +67,49 @@ public:  	}  }; -void TerminalLogger::process(const Message &msg) + +/* Class TerminalLogger */ + +/** + * Small class used internally for formated terminal output using ANSI/VT100 + * escape codes on supported terminals. + * + * TODO: Deactivate if using windows or use the corresponding API function. + */ + +std::string TerminalLogger::currentFilename() +{ +	if (!files.empty()) { +		return files.top().file; +	} +	return std::string{}; +} + +void TerminalLogger::processMessage(Message msg)  {  	Terminal t(useColor);  	// Print the file name -	if (msg.hasFile()) { -		os << t.color(Terminal::WHITE, true) << msg.file << t.reset(); +	std::string filename = currentFilename(); +	bool hasFile = !filename.empty(); +	if (hasFile) { +		os << t.color(Terminal::WHITE, true) << filename << t.reset();  	}  	// Print line and column number -	if (msg.hasLine()) { -		if (msg.hasFile()) { +	if (msg.pos.hasLine()) { +		if (hasFile) {  			os << ':';  		} -		os << t.color(Terminal::WHITE, true) << msg.line +		os << t.color(Terminal::WHITE, true) << msg.pos.line  		   << t.reset(); -		if (msg.hasColumn()) { -			os << ':' << msg.column; +		if (msg.pos.hasColumn()) { +			os << ':' << msg.pos.column;  		}  	}  	// Print the optional seperator -	if (msg.hasFile() || msg.hasLine()) { +	if (hasFile || msg.pos.hasLine()) {  		os << ": ";  	} @@ -156,6 +134,38 @@ void TerminalLogger::process(const Message &msg)  	// Print the actual message  	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) { +			os << "[...] "; +			relPos += 6; +		} +		os << msg.ctx.text; +		if (msg.ctx.truncatedEnd) { +			os << " [...]"; +		} +		os << std::endl; +		for (size_t i = 0; i < relPos; i++) { +			os << ' '; +		} +		os << t.color(Terminal::GREEN) << '^' << t.reset() << std::endl; +	} +} + +size_t TerminalLogger::processPushFile(File file) +{ +	files.push(file); +	return files.size(); +} + +size_t TerminalLogger::processPopFile() +{ +	files.pop(); +	return files.size();  } + +  } diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp index e6b97f4..6366f9a 100644 --- a/src/core/common/Logger.hpp +++ b/src/core/common/Logger.hpp @@ -35,6 +35,7 @@  #include <vector>  #include "Exceptions.hpp" +#include "TextCursor.hpp"  namespace ousia { @@ -90,6 +91,40 @@ static constexpr Severity DEFAULT_MIN_SEVERITY = Severity::DEBUG;  class Logger {  public:  	/** +	 * Describes an included file. +	 */ +	struct File { +		/** +		 * Is the name of the file. +		 */ +		std::string file; + +		/** +		 * Position at which the file was included. +		 */ +		TextCursor::Position pos; + +		/** +		 * Context in which the file was included. +		 */ +		TextCursor::Context ctx; + +		/** +		 * Constructor of the File 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. +		 */ +		File(std::string file, TextCursor::Position pos, +		     TextCursor::Context ctx) +		    : file(file), pos(pos), ctx(ctx) +		{ +		} +	}; + +	/**  	 * The message struct represents a single log message and all information  	 * attached to it.  	 */ @@ -105,80 +140,42 @@ public:  		std::string msg;  		/** -		 * Refers to the file which provides the context for this error message. -		 * May be empty. +		 * Position in the text the message refers to.  		 */ -		std::string file; +		TextCursor::Position pos;  		/** -		 * Line in the above file the error message refers to. Ignored if -		 * smaller than zero. +		 * Context the message refers to.  		 */ -		int line; - -		/** -		 * Column in the above file the error message refers to. Ignored if -		 * smaller than zero. -		 */ -		int column; +		TextCursor::Context ctx;  		/**  		 * Constructor of the Message struct.  		 *  		 * @param severity describes the message severity.  		 * @param msg contains the actual message. -		 * @param file provides the context the message refers to. May be empty.  		 * @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, std::string file, int line, -		        int column) +		Message(Severity severity, std::string msg, TextCursor::Position pos, +		        TextCursor::Context ctx)  		    : severity(severity),  		      msg(std::move(msg)), -		      file(std::move(file)), -		      line(line), -		      column(column){}; - -		/** -		 * Returns true if the file string is set. -		 * -		 * @return true if the file string is set. -		 */ -		bool hasFile() const { return !file.empty(); } - -		/** -		 * Returns true if the line is set. -		 * -		 * @return true if the line number is a non-negative integer. -		 */ -		bool hasLine() const { return line >= 0; } - -		/** -		 * Returns true if column and line are set (since a column has no -		 * significance without a line number). -		 * -		 * @return true if line number and column number are non-negative -		 * integers. -		 */ -		bool hasColumn() const { return hasLine() && column >= 0; } +		      pos(std::move(pos)), +		      ctx(std::move(ctx)){};  	};  private:  	/**  	 * Minimum severity a log message should have before it is discarded.  	 */ -	Severity minSeverity; +	const Severity minSeverity;  	/**  	 * Maximum encountered log message severity.  	 */  	Severity maxEncounteredSeverity; -	/** -	 * Stack containing the current file names that have been processed. -	 */ -	std::stack<std::string> filenameStack; -  protected:  	/**  	 * Function to be overriden by child classes to actually display or store @@ -188,7 +185,23 @@ protected:  	 * @param msg is an instance of the Message struct containing the data that  	 * should be logged.  	 */ -	virtual void process(const Message &msg){}; +	virtual void processMessage(Message msg) {} + +	/** +	 * Called whenever a new file is pushed onto the stack. +	 * +	 * @param file is the file that should be pushed onto the stack. +	 * @return the stack depth after the file has been pushed. +	 */ +	virtual size_t processPushFile(File file) { return 0; } + +	/** +	 * Called whenever a file is popped from the stack. +	 * +	 * @return the stack depth after the current file has been removed from the +	 * stack. +	 */ +	virtual size_t processPopFile() { return 0; }  public:  	/** @@ -210,51 +223,30 @@ public:  	virtual ~Logger(){};  	/** -	 * Logs the given message. Most generic log function. -	 * -	 * @param severity is the severity of the log message. -	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void log(Severity severity, const std::string &msg, const std::string &file, -	         int line = -1, int column = -1); - -	/**  	 * Logs the given message. The file name is set to the topmost file name on  	 * the file name stack.  	 *  	 * @param severity is the severity of the log message.  	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. +	 * @param pos is the position the log message refers to. +	 * @param ctx describes the context of the log message.  	 */ -	void log(Severity severity, const std::string &msg, int line = -1, -	         int column = -1) +	void log(Severity severity, std::string msg, +	         TextCursor::Position pos = TextCursor::Position{}, +	         TextCursor::Context ctx = TextCursor::Context{})  	{ -		log(severity, msg, currentFilename(), line, column); -	} - -	/** -	 * Logs the given message. The file name is set to the topmost file name on -	 * the file name stack. -	 * -	 * @param severity is the severity of the log message. -	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. -	 * @tparam PosType is the actual type of pos and must implement a getLine -	 * and getColumn function. -	 */ -	template <class PosType> -	void logAt(Severity severity, const std::string &msg, const PosType &pos) -	{ -		log(severity, msg, pos.getLine(), pos.getColumn()); +		// 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)}); +		}  	}  	/** @@ -264,278 +256,188 @@ public:  	 */  	void log(const LoggableException &ex)  	{ -		log(Severity::ERROR, ex.msg, -		    ex.file.empty() ? currentFilename() : ex.file, ex.line, ex.column); -	} - -	/** -	 * Logs a debug message. The file name is set to the topmost file name on -	 * the file name stack. -	 * -	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void debug(const std::string &msg, const std::string &file, int line = -1, -	           int column = -1) -	{ -		log(Severity::DEBUG, msg, file, line, column); -	} - -	/** -	 * Logs a debug message. The file name is set to the topmost file name on -	 * the file name stack. -	 * -	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void debug(const std::string &msg, int line = -1, int column = -1) -	{ -		debug(msg, currentFilename(), line, column); +		log(Severity::ERROR, ex.msg, ex.getPosition(), ex.getContext());  	}  	/** -	 * Logs a debug message. The file name is set to the topmost file name on +	 * Logs the given message. The file name is set to the topmost file name on  	 * the file name stack.  	 *  	 * @param severity is the severity of the log message.  	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @param pos is a reference to a variable which provides position and +	 * context information.  	 */  	template <class PosType> -	void debugAt(const std::string &msg, const PosType &pos) +	void logAt(Severity severity, std::string msg, PosType &pos)  	{ -		debug(msg, pos.getLine(), pos.getColumn()); +		log(severity, std::move(msg), pos.getPosition(), pos.getContext());  	}  	/** -	 * Logs a note. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a debug message. Debug messages will be discarded if the software +	 * is compiled in the release mode (with the NDEBUG flag).  	 *  	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void note(const std::string &msg, const std::string &file, int line = -1, -	          int column = -1) +	 * @param pos describes the position of the debug message. +	 * @param ctx describes the context of the debug message. +	 */ +	void debug(std::string msg, +	           TextCursor::Position pos = TextCursor::Position{}, +	           TextCursor::Context ctx = TextCursor::Context{})  	{ -		log(Severity::NOTE, msg, file, line, column); +#ifndef NDEBUG +		log(Severity::DEBUG, std::move(msg), std::move(pos), std::move(ctx)); +#endif  	}  	/** -	 * Logs a note. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a debug message. Debug messages will be discarded if the software +	 * is compiled in the release mode.  	 *  	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. +	 * @param pos is a reference to a variable which provides position and +	 * context information.  	 */ -	void note(const std::string &msg, int line = -1, int column = -1) +	template<class PosType> +	void debug(std::string msg, PosType &pos)  	{ -		note(msg, currentFilename(), line, column); +#ifndef NDEBUG +		logAt(Severity::DEBUG, std::move(msg), pos); +#endif  	}  	/** -	 * Logs a note. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a note.  	 *  	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @param pos describes the position of the note. +	 * @param ctx describes the context of the note.  	 */ -	template <class PosType> -	void noteAt(const std::string &msg, const PosType &pos) +	void note(std::string msg, +	          TextCursor::Position pos = TextCursor::Position{}, +	          TextCursor::Context ctx = TextCursor::Context{})  	{ -		note(msg, pos.getLine(), pos.getColumn()); +		log(Severity::NOTE, std::move(msg), std::move(pos), std::move(ctx));  	}  	/** -	 * Logs a warning. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a note.  	 *  	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void warning(const std::string &msg, const std::string &file, int line = -1, -	             int column = -1) +	 * @param pos is a reference to a variable which provides position and +	 * context information. +	 */ +	template<class PosType> +	void note(std::string msg, PosType &pos)  	{ -		log(Severity::WARNING, msg, file, line, column); +		logAt(Severity::NOTE, std::move(msg), pos);  	}  	/** -	 * Logs a warning. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a warning.  	 *  	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @param pos describes the position of the warning. +	 * @param ctx describes the context of the warning.  	 */ -	template <class PosType> -	void warningAt(const std::string &msg, const PosType &pos) +	void warning(std::string msg, +	             TextCursor::Position pos = TextCursor::Position{}, +	             TextCursor::Context ctx = TextCursor::Context{})  	{ -		warning(msg, pos.getLine(), pos.getColumn()); +		log(Severity::WARNING, std::move(msg), std::move(pos), std::move(ctx));  	}  	/** -	 * Logs a warning. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a warning.  	 *  	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. +	 * @param pos is a reference to a variable which provides position and +	 * context information.  	 */ -	void warning(const std::string &msg, int line = -1, int column = -1) +	template<class PosType> +	void warning(std::string msg, PosType &pos)  	{ -		warning(msg, currentFilename(), line, column); +		logAt(Severity::WARNING, std::move(msg), pos);  	}  	/** -	 * Logs an error message. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs an error message.  	 *  	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void error(const std::string &msg, const std::string &file, int line = -1, -	           int column = -1) +	 * @param pos is the position at which the error occured. +	 * @param ctx describes the context in which the error occured. +	 */ +	void error(std::string msg, +	           TextCursor::Position pos = TextCursor::Position{}, +	           TextCursor::Context ctx = TextCursor::Context{})  	{ -		log(Severity::ERROR, msg, file, line, column); +		log(Severity::ERROR, std::move(msg), std::move(pos), std::move(ctx));  	}  	/** -	 * Logs an error message. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs an error message.  	 *  	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. +	 * @param pos is a reference to a variable which provides position and +	 * context information.  	 */ -	void error(const std::string &msg, int line = -1, int column = -1) +	template<class PosType> +	void error(std::string msg, PosType &pos)  	{ -		error(msg, currentFilename(), line, column); +		logAt(Severity::ERROR, std::move(msg), pos);  	}  	/** -	 * Logs an error message. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a fatal error message.  	 *  	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @param pos is the position at which the error occured. +	 * @param ctx describes the context in which the error occured.  	 */ -	template <class PosType> -	void errorAt(const std::string &msg, const PosType &pos) +	void fatalError(std::string msg, +	                TextCursor::Position pos = TextCursor::Position{}, +	                TextCursor::Context ctx = TextCursor::Context{})  	{ -		error(msg, pos.getLine(), pos.getColumn()); +		log(Severity::FATAL_ERROR, std::move(msg), std::move(pos), +		    std::move(ctx));  	} -	/** -	 * Logs a fatal error. The file name is set to the topmost file name on -	 * the file name stack. -	 * -	 * @param msg is the actual log message. -	 * @param file is the name of the file the message refers to. May be empty. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. -	 */ -	void fatalError(const std::string &msg, const std::string &file, -	                int line = -1, int column = -1) -	{ -		log(Severity::FATAL_ERROR, msg, file, line, column); -	}  	/** -	 * Logs a fatal error. The file name is set to the topmost file name on -	 * the file name stack. +	 * Logs a fatal error message.  	 *  	 * @param msg is the actual log message. -	 * @param line is the line in the above file at which the error occured. -	 * Ignored if negative. -	 * @param column is the column in the above file at which the error occured. -	 * Ignored if negative. +	 * @param pos is a reference to a variable which provides position and +	 * context information.  	 */ -	void fatalError(const std::string &msg, int line = -1, int column = -1) +	template<class PosType> +	void fatalError(std::string msg, PosType &pos)  	{ -		fatalError(msg, currentFilename(), line, column); +		logAt(Severity::FATAL_ERROR, std::move(msg), pos);  	}  	/** -	 * Logs a fatal error. The file name is set to the topmost file name on -	 * the file name stack. +	 * Pushes a new file name onto the internal filename stack.  	 * -	 * @param msg is the actual log message. -	 * @param pos is a const reference to a variable which provides position -	 * information. +	 * @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.  	 */ -	template <class PosType> -	void fatalErrorAt(const std::string &msg, const PosType &pos) +	size_t pushFile(std::string name, +	                TextCursor::Position pos = TextCursor::Position{}, +	                TextCursor::Context ctx = TextCursor::Context{})  	{ -		fatalError(msg, pos.getLine(), pos.getColumn()); +		return processPushFile( +		    File(std::move(name), std::move(pos), std::move(ctx)));  	}  	/** -	 * Pushes a new file name onto the internal filename stack. -	 * -	 * @param name is the name of the file that should be added to the filename -	 * stack. -	 * @return the size of the filename stack. This number can be passed to the -	 * "unwindFilenameStack" method in order to return the stack to state it was -	 * in after this function has been called. -	 */ -	unsigned int pushFilename(const std::string &name); - -	/**  	 * Pops the filename from the internal filename stack.  	 *  	 * @return the current size of the filename stack.  	 */ -	unsigned int popFilename(); - -	/** -	 * Pops elements from the filename stack while it has more elements than -	 * the given number and the stack is non-empty. -	 * -	 * @param pos is the position the filename stack should be unwound to. Use -	 * a number returned by pushFilename. -	 */ -	void unwindFilenameStack(unsigned int pos); - -	/** -	 * Returns the topmost filename from the internal filename stack. -	 * -	 * @return the topmost filename from the filename stack or an empty string -	 * if the filename stack is empty. -	 */ -	std::string currentFilename() -	{ -		return filenameStack.empty() ? std::string{} : filenameStack.top(); -	} +	size_t popFile() { return processPopFile(); }  	/**  	 * Returns the maximum severity that was encountered by the Logger but at @@ -553,14 +455,6 @@ public:  	 * @return the minimum severity.  	 */  	Severity getMinSeverity() { return minSeverity; } - -	/** -	 * Sets the minimum severity. Messages with a smaller severity will be -	 * discarded. Only new messages will be filtered according to the new value. -	 * -	 * @param severity is the minimum severity for new log messages. -	 */ -	void setMinSeverity(Severity severity) { minSeverity = severity; }  };  /** @@ -580,11 +474,20 @@ private:  	 */  	bool useColor; -protected:  	/** -	 * Implements the process function and logs the messages to the output. +	 * Stack used to keep the file references.  	 */ -	void process(const Message &msg) override; +	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; +	size_t processPushFile(File file) override; +	size_t processPopFile() override;  public:  	/** @@ -602,6 +505,12 @@ public:  	    : Logger(minSeverity), os(os), useColor(useColor)  	{  	} + +	/** +	 * Returns the name of the topmost file. +	 */ +	std::string currentFilename(); +  };  } diff --git a/src/core/common/TextCursor.hpp b/src/core/common/TextCursor.hpp new file mode 100644 index 0000000..2633345 --- /dev/null +++ b/src/core/common/TextCursor.hpp @@ -0,0 +1,168 @@ +/* +    Ousía +    Copyright (C) 2014, 2015  Benjamin Paaßen, Andreas Stöckel + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _OUSIA_TEXT_CURSOR_HPP_ +#define _OUSIA_TEXT_CURSOR_HPP_ + +namespace ousia { +namespace TextCursor { + +/** + * Type used for representing line or column positions. + */ +using PosType = unsigned int; + +/** + * Struct representing a position within the text. A position is defined by a + * byte offset (which is always reproducable), a line number and a column + * number. + */ +struct Position { +	/** +	 * Current line, starting with one. +	 */ +	PosType line; + +	/** +	 * Current column, starting with one. +	 */ +	PosType column; + +	/** +	 * Current byte offset. +	 */ +	size_t offs; + +	/** +	 * Default constructor of the Position struct, initializes all memebers +	 * with zero. +	 */ +	Position() : line(0), column(0), offs(0) {} + +	/** +	 * Creates a new Position struct with only a line and no column. +	 * +	 * @param line is the line number. +	 * @param column is the column number. +	 */ +	Position(PosType line) : line(line), column(0), offs(0) {} + +	/** +	 * Creates a new Position struct with a line and column. +	 * +	 * @param line is the line number. +	 * @param column is the column number. +	 */ +	Position(PosType line, PosType column) : line(line), column(column), offs(0) +	{ +	} + +	/** +	 * Creates a new Position struct with a line, column and byte offset. +	 * +	 * @param line is the line number. +	 * @param column is the column number. +	 * @param offs is the byte offset. +	 */ +	Position(PosType line, PosType column, size_t offs) +	    : line(line), column(column), offs(offs) +	{ +	} + +	/** +	 * Returns true, if the line number is valid, false otherwise. +	 * +	 * @return true for valid line numbers. +	 */ +	bool hasLine() const { return line > 0; } + +	/** +	 * Returns true, if the column number is valid, false otherwise. +	 * +	 * @return true for valid column numbers. +	 */ +	bool hasColumn() const { return column > 0; } +}; + +/** + * Represents the current context a CharReader is in. Used for building error + * messages. + */ +struct Context { +	/** +	 * Set to the content of the current line. +	 */ +	std::string text; + +	/** +	 * Relative position (in characters) within that line. May point to +	 * locations beyond the text content. +	 */ +	PosType relPos; + +	/** +	 * Set to true if the beginning of the line has been truncated (because +	 * the reader position is too far away from the actual position of the +	 * line). +	 */ +	bool truncatedStart; + +	/** +	 * Set to true if the end of the line has been truncated (because the +	 * reader position is too far away from the actual end position of the +	 * line. +	 */ +	bool truncatedEnd; + +	/** +	 * Default constructor, initializes all members with zero values. +	 */ +	Context() : text(), relPos(0), truncatedStart(false), truncatedEnd(false) {} + +	/** +	 * Constructor of the Context class. +	 * +	 * @param text is the current line the text cursor is at. +	 * @param relPos is the relative position of the text cursor within that +	 * line. +	 * @param truncatedStart specifies whether the text was truncated at the +	 * beginning. +	 * @param truncatedEnd specifies whether the text was truncated at the +	 * end. +	 */ +	Context(std::string text, size_t relPos, bool truncatedStart, +	        bool truncatedEnd) +	    : text(std::move(text)), +	      relPos(relPos), +	      truncatedStart(truncatedStart), +	      truncatedEnd(truncatedEnd) +	{ +	} + +	/** +	 * Returns true the context text is not empty. +	 * +	 * @return true if the context is valid and e.g. should be printed. +	 */ +	bool valid() const { return !text.empty(); } +}; +} +} + +#endif /* _OUSIA_TEXT_CURSOR_HPP_ */ + diff --git a/src/core/common/VariantReader.cpp b/src/core/common/VariantReader.cpp index e611842..a31a658 100644 --- a/src/core/common/VariantReader.cpp +++ b/src/core/common/VariantReader.cpp @@ -101,7 +101,7 @@ private:  		// Check whether the given character is valid  		int v = charValue(c);  		if (v < 0 || v >= base) { -			logger.errorAt(ERR_UNEXPECTED_CHAR, reader); +			logger.error(ERR_UNEXPECTED_CHAR, reader);  			return false;  		} @@ -121,7 +121,7 @@ private:  		// Check for any overflows  		if (a < 0 || n < 0 || d < 0 || e < 0) { -			logger.errorAt(ERR_TOO_LARGE, reader); +			logger.error(ERR_TOO_LARGE, reader);  			return false;  		}  		return true; @@ -203,7 +203,7 @@ bool Number::parse(CharReader &reader, Logger &logger,  					case '-':  						// Do not allow multiple minus signs  						if (state == State::HAS_MINUS) { -							logger.errorAt(ERR_UNEXPECTED_CHAR, reader); +							logger.error(ERR_UNEXPECTED_CHAR, reader);  							return false;  						}  						state = State::HAS_MINUS; @@ -259,7 +259,7 @@ bool Number::parse(CharReader &reader, Logger &logger,  					case 'e':  					case 'E':  						if (state == State::LEADING_POINT) { -							logger.errorAt(ERR_UNEXPECTED_CHAR, reader); +							logger.error(ERR_UNEXPECTED_CHAR, reader);  							return false;  						}  						state = State::EXP_INIT; @@ -276,7 +276,7 @@ bool Number::parse(CharReader &reader, Logger &logger,  			case State::EXP_INIT:  				if (c == '-') {  					if (state == State::EXP_HAS_MINUS) { -						logger.errorAt(ERR_UNEXPECTED_CHAR, reader); +						logger.error(ERR_UNEXPECTED_CHAR, reader);  						return false;  					}  					state = State::EXP_HAS_MINUS; @@ -303,7 +303,7 @@ bool Number::parse(CharReader &reader, Logger &logger,  	    state == State::EXP) {  		return true;  	} -	logger.errorAt(ERR_UNEXPECTED_END, reader); +	logger.error(ERR_UNEXPECTED_END, reader);  	return false;  } @@ -322,7 +322,7 @@ template <class T>  static std::pair<bool, T> error(CharReader &reader, Logger &logger,                                  const char *err, T res)  { -	logger.errorAt(err, reader); +	logger.error(err, reader);  	return std::make_pair(false, std::move(res));  } @@ -410,7 +410,7 @@ std::pair<bool, std::string> VariantReader::parseString(  						if (Utils::isNumeric(c)) {  							// TODO: Parse octal 000 sequence  						} else { -							logger.errorAt(ERR_INVALID_ESCAPE, reader); +							logger.error(ERR_INVALID_ESCAPE, reader);  						}  						break;  				} @@ -476,7 +476,7 @@ std::pair<bool, Variant::arrayType> VariantReader::parseArray(  				} else if (!Utils::isWhitespace(c)) {  					hadError = true;  					state = STATE_RESYNC; -					logger.errorAt(ERR_UNEXPECTED_CHAR, reader); +					logger.error(ERR_UNEXPECTED_CHAR, reader);  				}  				reader.consumePeek();  				break; diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 9a7b4d8..824219a 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -204,11 +204,15 @@ Rooted<Node> XmlParser::parse(std::istream &is, ParserContext &ctx)  		// Parse the data and handle any XML error  		if (!XML_ParseBuffer(&p, bytesRead, bytesRead == 0)) { -			const int line = XML_GetCurrentLineNumber(&p); -			const int column = XML_GetCurrentColumnNumber(&p); +			const TextCursor::PosType line = +			    static_cast<TextCursor::PosType>(XML_GetCurrentLineNumber(&p)); +			const TextCursor::PosType column = static_cast<TextCursor::PosType>( +			    XML_GetCurrentColumnNumber(&p)); +			const size_t offs = XML_GetCurrentByteIndex(&p);  			const XML_Error code = XML_GetErrorCode(&p);  			const std::string msg = std::string{XML_ErrorString(code)}; -			throw ParserException{"XML Syntax Error: " + msg, line, column}; +			throw ParserException{"XML Syntax Error: " + msg, line, column, +			                      offs};  		}  		// Abort once there are no more bytes in the stream diff --git a/test/core/common/CharReaderTest.cpp b/test/core/common/CharReaderTest.cpp index 06b9d45..9c1026c 100644 --- a/test/core/common/CharReaderTest.cpp +++ b/test/core/common/CharReaderTest.cpp @@ -660,8 +660,8 @@ TEST(CharReaderTest, context)  	// Retrieval at beginning of stream  	{  		CharReader reader{testStr}; -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("first line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("first line", ctx.text);  		ASSERT_EQ(0U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -670,13 +670,13 @@ TEST(CharReaderTest, context)  	// Retrieval in middle of line  	{  		CharReader reader{testStr}; -		CharReader::Context ctx = reader.getContext(80); +		TextCursor::Context ctx = reader.getContext(80);  		char c;  		for (int i = 0; i < 5; i++)  			reader.read(c); -		ASSERT_EQ("first line", ctx.line); +		ASSERT_EQ("first line", ctx.text);  		ASSERT_EQ(0U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -690,8 +690,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 11; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("first line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("first line", ctx.text);  		ASSERT_EQ(10U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -705,8 +705,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 5; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(3); -		ASSERT_EQ("t l", ctx.line); +		TextCursor::Context ctx = reader.getContext(3); +		ASSERT_EQ("t l", ctx.text);  		ASSERT_EQ(1U, ctx.relPos);  		ASSERT_TRUE(ctx.truncatedStart);  		ASSERT_TRUE(ctx.truncatedEnd); @@ -720,8 +720,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 12; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("second line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("second line", ctx.text);  		ASSERT_EQ(0U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -735,8 +735,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 23; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("second line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("second line", ctx.text);  		ASSERT_EQ(11U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -750,8 +750,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 24; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("last line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("last line", ctx.text);  		ASSERT_EQ(0U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -765,8 +765,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 28; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("last line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("last line", ctx.text);  		ASSERT_EQ(4U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -780,8 +780,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 28; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(3); -		ASSERT_EQ("t l", ctx.line); +		TextCursor::Context ctx = reader.getContext(3); +		ASSERT_EQ("t l", ctx.text);  		ASSERT_EQ(1U, ctx.relPos);  		ASSERT_TRUE(ctx.truncatedStart);  		ASSERT_TRUE(ctx.truncatedEnd); @@ -795,8 +795,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 100; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(80); -		ASSERT_EQ("last line", ctx.line); +		TextCursor::Context ctx = reader.getContext(80); +		ASSERT_EQ("last line", ctx.text);  		ASSERT_EQ(9U, ctx.relPos);  		ASSERT_FALSE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); @@ -810,8 +810,8 @@ TEST(CharReaderTest, context)  		for (int i = 0; i < 100; i++)  			reader.read(c); -		CharReader::Context ctx = reader.getContext(4); -		ASSERT_EQ("line", ctx.line); +		TextCursor::Context ctx = reader.getContext(4); +		ASSERT_EQ("line", ctx.text);  		ASSERT_EQ(4U, ctx.relPos);  		ASSERT_TRUE(ctx.truncatedStart);  		ASSERT_FALSE(ctx.truncatedEnd); diff --git a/test/core/common/LoggerTest.cpp b/test/core/common/LoggerTest.cpp index 54c67f9..bb31fa6 100644 --- a/test/core/common/LoggerTest.cpp +++ b/test/core/common/LoggerTest.cpp @@ -25,31 +25,38 @@  namespace ousia {  struct Pos { -	int line, column; -	Pos(int line, int column) : line(line), column(column){}; -	int getLine() const { return line; } -	int getColumn() const { return column; } +	TextCursor::Position pos; +	TextCursor::Context ctx; + +	Pos(TextCursor::Position pos = TextCursor::Position{}, +	    TextCursor::Context ctx = TextCursor::Context{}) +	    : pos(pos), ctx(ctx){}; + +	TextCursor::Position getPosition() { return pos; } +	TextCursor::Context getContext() { return ctx; }  };  TEST(TerminalLogger, log)  {  	// Test for manual visual expection only -- no assertions  	TerminalLogger logger{std::cerr, true}; -	logger.pushFilename("test.odp"); +	logger.pushFile("test.odp"); -	logger.debug("This is a test debug message", 10, 20); -	logger.debug("This is a test debug message with no column", 10); +	logger.debug("This is a test debug message", TextCursor::Position{10, 20}); +	logger.debug("This is a test debug message with no column", +	             TextCursor::Position{10});  	logger.debug("This is a test debug message with no line"); -	logger.debug("This is a test debug message with no file", ""); -	logger.debug("This is a test debug message with no file but a line", "", -	             10); -	logger.debug( -	    "This is a test debug message with no file but a line and a column", "", -	    10, 20); -	logger.note("This is a test note", 10, 20); -	logger.warning("This is a test warning", 10, 20); -	logger.error("This is a test error", 10, 20); -	logger.fatalError("This is a test fatal error!", 10, 20); +	logger.note("This is a test note", TextCursor::Position{10, 20}); +	logger.warning("This is a test warning", TextCursor::Position{10, 20}); +	logger.error("This is a test error", TextCursor::Position{10, 20}); +	logger.fatalError("This is a test fatal error!", +	                  TextCursor::Position{10, 20}); + +	logger.error("This is a test error with context", +	             TextCursor::Position{10, 20}, +	             TextCursor::Context{"int bla = blub;", 10, true, false}); + +	Pos pos(TextCursor::Position{10, 20});  	try {  		throw LoggableException{"An exception"}; @@ -59,16 +66,13 @@ TEST(TerminalLogger, log)  	}  	try { -		throw LoggableException{"An exception at position", Pos(10, 20)}; +		throw LoggableException{"An exception at position", pos};  	}  	catch (const LoggableException &ex) {  		logger.log(ex);  	} -	logger.logAt(Severity::ERROR, "This is a positioned log message", -	             Pos(10, 20)); -	logger.debugAt("This is a positioned debug message", Pos(10, 20)); -	logger.noteAt("This is a positioned log error", Pos(10, 20)); +	logger.logAt(Severity::ERROR, "This is a positioned log message", pos);  }  } diff --git a/test/plugins/xml/XmlParserTest.cpp b/test/plugins/xml/XmlParserTest.cpp index 7dc8c24..39b1a9d 100644 --- a/test/plugins/xml/XmlParserTest.cpp +++ b/test/plugins/xml/XmlParserTest.cpp @@ -36,7 +36,7 @@ TEST(XmlParser, mismatchedTagException)  		p.parse("<document>\n</document2>", ctx);  	}  	catch (ParserException ex) { -		ASSERT_EQ(2, ex.line); +		ASSERT_EQ(2U, ex.pos.line);  		hadException = true;  	}  	ASSERT_TRUE(hadException); | 
