Add line/column reporting to exceptions, update it to work with

std::exception as a base, slightly change semantics of entityRef()
function so that it can report line/col.
This commit is contained in:
Laurence Withers 2006-08-07 11:06:31 +01:00
parent 23f18e10c5
commit 44147acacf
11 changed files with 106 additions and 29 deletions

View File

@ -5,3 +5,7 @@
*/ */
#endif #endif
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -177,8 +177,9 @@ public:
/*! \brief Entity reference. /*! \brief Entity reference.
\param name The name of the entity being referred to. \param name The name of the entity being referred to.
\returns The expanded text. \param[out] value The expanded text.
\throws UnknownEntity if the entity is unknown. \retval true if the entity is valid.
\retval false if the entity is not valid.
This function is called whenever an entity reference is encountered, This function is called whenever an entity reference is encountered,
and \a expandEntities is \a true in your parser. The five standard and \a expandEntities is \a true in your parser. The five standard
@ -186,12 +187,18 @@ public:
but anything else will be passed to this function. but anything else will be passed to this function.
*/ */
virtual std::wstring entityRef(const std::wstring& name) virtual bool entityRef(const std::wstring& name, std::wstring& value)
{ {
throw UnknownEntity(name); (void)name;
(void)value;
return false;
} }
}; };
}; };
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -62,3 +62,7 @@ void Decoder::restart()
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -70,3 +70,7 @@ private:
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -8,14 +8,14 @@ namespace lsx {
Exception::Exception(const std::wstring& reason) Exception::Exception(const std::wstring& reason, int line, int col)
: reason(reason) : reason(reason), line(line), col(col)
{ {
} }
const char* Exception::what() const char* Exception::what() const throw()
{ {
if(utf8Reason.empty()) utf8Reason = utf8::encode(reason, true); if(utf8Reason.empty()) utf8Reason = utf8::encode(reason, true);
return utf8Reason.c_str(); return utf8Reason.c_str();
@ -23,39 +23,46 @@ const char* Exception::what()
NotWellFormed::NotWellFormed(const std::wstring& error) NotWellFormed::NotWellFormed(const std::wstring& error, int line, int col)
: Exception(format(error)), error(error) : Exception(format(error, line, col), line, col), error(error)
{ {
} }
std::wstring NotWellFormed::format(const std::wstring& error) std::wstring NotWellFormed::format(const std::wstring& error, int line, int col)
{ {
std::wostringstream ost; std::wostringstream ost;
ost << L"Streamed XML is not well formed:\n" ost << L"Streamed XML is not well formed:"
<< error; << L"\n line : " << line + 1
<< L"\n column: " << col + 1
<< L"\n reason: " << error;
return ost.str(); return ost.str();
} }
UnknownEntity::UnknownEntity(const std::wstring& name) UnknownEntity::UnknownEntity(const std::wstring& name, int line, int col)
: Exception(format(name)), name(name) : Exception(format(name, line, col), line, col), name(name)
{ {
} }
std::wstring UnknownEntity::format(const std::wstring& name) std::wstring UnknownEntity::format(const std::wstring& name, int line, int col)
{ {
std::wostringstream ost; std::wostringstream ost;
ost << L"Encountered an unknown entity named '" ost << L"Encountered an unknown entity in the Streamed XML:"
<< name << L"\n line : " << line + 1
<< L"' in the Streamed XML."; << L"\n column: " << col + 1
<< L"\n name : " << name;
return ost.str(); return ost.str();
} }
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -14,30 +14,38 @@ This class is the base class of all exceptions. It simply provides a mechanism f
message; more specific details must be stored in base classes. message; more specific details must be stored in base classes.
*/ */
class Exception { class Exception : public std::exception {
public: public:
/*! \brief Constructor. /*! \brief Constructor.
\param reason Reason for the exception. \param reason Reason for the exception.
\param line Line number of input (starting from 0).
\param col Column of input (starting from 0).
The constructor simply stores the reason for the exception, which may be later accessed for The constructor simply stores the reason for the exception, which may be later accessed for
reporting to the user. reporting to the user.
*/ */
Exception(const std::wstring& reason); Exception(const std::wstring& reason, int line, int col);
/// Destructor. /// Destructor.
virtual ~Exception() throw() virtual ~Exception() throw()
{ } { }
/// Find what caused the error. /// Find what caused the error.
virtual const char* what(); virtual const char* what() const throw();
/// Reason for the exception. /// Reason for the exception.
const std::wstring reason; const std::wstring reason;
/// Line on which the exception occurred (starting from 0).
const int line;
/// Column on which the exception occurred (starting from 0).
const int col;
private: private:
std::string utf8Reason; mutable std::string utf8Reason;
}; };
@ -45,18 +53,20 @@ private:
/// Thrown when XML is not well formed. /// Thrown when XML is not well formed.
class NotWellFormed : public Exception { class NotWellFormed : public Exception {
private: private:
static std::wstring format(const std::wstring& error); static std::wstring format(const std::wstring& error, int line, int col);
public: public:
/*! \brief Constructor. /*! \brief Constructor.
\param error Reason for the error. \param error Reason for the error.
\param line Line on which the exception occurred.
\param col Column on which the exception occurred.
The constructor will store the reason for the error. It will also prepare a suitable message The constructor will store the reason for the error. It will also prepare a suitable message
for the Exception base class. for the Exception base class.
*/ */
NotWellFormed(const std::wstring& error); NotWellFormed(const std::wstring& error, int line, int col);
/// Destructor. /// Destructor.
virtual ~NotWellFormed() throw() virtual ~NotWellFormed() throw()
@ -71,18 +81,20 @@ public:
/// Thrown when an unknown entity is referred to. /// Thrown when an unknown entity is referred to.
class UnknownEntity : public Exception { class UnknownEntity : public Exception {
private: private:
static std::wstring format(const std::wstring& name); static std::wstring format(const std::wstring& name, int line, int col);
public: public:
/*! \brief Constructor. /*! \brief Constructor.
\param name Name of the unknown entity. \param name Name of the unknown entity.
\param line Line on which the exception occurred.
\param col Column on which the exception occurred.
The constructor will store the name of the unknown entity. It will also prepare a suitable The constructor will store the name of the unknown entity. It will also prepare a suitable
message for the Exception base class. message for the Exception base class.
*/ */
UnknownEntity(const std::wstring& name); UnknownEntity(const std::wstring& name, int line, int col);
/// Destructor. /// Destructor.
virtual ~UnknownEntity() throw() virtual ~UnknownEntity() throw()
@ -95,3 +107,7 @@ public:
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -22,3 +22,7 @@ class UnknownEntity;
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -37,6 +37,8 @@ void Parser::reset()
skipNextNewline = false; skipNextNewline = false;
state = StateNone; state = StateNone;
restartCount = 0; restartCount = 0;
line = 0;
col = 0;
} }
@ -59,7 +61,7 @@ void Parser::feedChar(wchar_t ch)
#define ERROR(_reason) do { \ #define ERROR(_reason) do { \
state = StateError; \ state = StateError; \
throw NotWellFormed(_reason); \ throw NotWellFormed(_reason, line, col); \
}while(0) }while(0)
if(ch == xmlRestartMarker[restartCount]) { if(ch == xmlRestartMarker[restartCount]) {
if(++restartCount == 11) { if(++restartCount == 11) {
@ -84,11 +86,15 @@ void Parser::feedChar(wchar_t ch)
skipNextNewline = true; skipNextNewline = true;
ch = L'\n'; ch = L'\n';
c = ClassWhitespace; c = ClassWhitespace;
++line;
col = 0;
goto doBuffer; goto doBuffer;
case 0x2028: case 0x2028:
ch = L'\n'; ch = L'\n';
c = ClassWhitespace; c = ClassWhitespace;
++line;
col = 0;
break; break;
case L' ': case L' ':
@ -101,6 +107,8 @@ void Parser::feedChar(wchar_t ch)
if(skipNextNewline) return; if(skipNextNewline) return;
ch = L'\n'; ch = L'\n';
c = ClassWhitespace; c = ClassWhitespace;
++line;
col = 0;
break; break;
case L':': case L':':
@ -566,6 +574,7 @@ doBuffer:
break; break;
} }
#undef ERROR #undef ERROR
++col;
} }
@ -577,9 +586,16 @@ std::wstring Parser::entityRef(const std::wstring& ent)
if(ent == L"apos") return L"'"; if(ent == L"apos") return L"'";
if(ent == L"lt") return L"<"; if(ent == L"lt") return L"<";
if(ent == L"gt") return L">"; if(ent == L"gt") return L">";
return callback->entityRef(ent);
std::wstring result;
if(callback->entityRef(ent, result)) return result;
throw UnknownEntity(ent, line, col);
} }
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -120,6 +120,9 @@ private:
bool skipNextNewline; bool skipNextNewline;
int elementDepth, xmlCount, restartCount; int elementDepth, xmlCount, restartCount;
// for reporting errors
int line, col;
public: public:
/*! \brief Constructor. /*! \brief Constructor.
@ -221,3 +224,7 @@ public:
} }
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -14,3 +14,7 @@
#include <sstream> #include <sstream>
#include <utf8> #include <utf8>
#include <stdint.h> #include <stdint.h>
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/

View File

@ -8,3 +8,7 @@
// Below are all the includes used throughout the library. // Below are all the includes used throughout the library.
/* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4
*/