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:
parent
23f18e10c5
commit
44147acacf
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue