Compare commits
19 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
0a86b2d57f | |
![]() |
f7fe4bb787 | |
![]() |
2f2e07b2e2 | |
![]() |
593bb8d80c | |
![]() |
bf2ca8d925 | |
![]() |
d46aaf2b2e | |
![]() |
9a33766c62 | |
![]() |
a24d2caad2 | |
![]() |
25af0958a6 | |
![]() |
71fda14981 | |
![]() |
f1fa8b5625 | |
![]() |
8e3798dbbc | |
![]() |
c2d02165d7 | |
![]() |
0cc4d09d65 | |
![]() |
a2ca4f8122 | |
![]() |
4533df2947 | |
![]() |
dc6a4cf430 | |
![]() |
4eec490403 | |
![]() |
44147acacf |
8
README
8
README
|
@ -1,4 +1,4 @@
|
|||
libStreamedXML
|
||||
libStreamedXML http://www.lwithers.me.uk/projects/libStreamedXML/
|
||||
========================================================================
|
||||
(c)2006, Laurence Withers, <l@lwithers.me.uk>.
|
||||
Released under the GNU GPLv2. See file COPYING or
|
||||
|
@ -11,4 +11,8 @@ To build: ./make.sh
|
|||
To install: ./make.sh install
|
||||
(you might want to set PREFIX, by default it's /usr/local)
|
||||
|
||||
@TODO@
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
libutf8++
|
||||
http://www.lwithers.me.uk/projects/libutf8++/
|
||||
|
|
6
make.sh
6
make.sh
|
@ -64,6 +64,7 @@ OUTPUT_DIRS="obj html"
|
|||
# none no special processing happens before each file
|
||||
# C #line directives are inserted before each file
|
||||
# and VERSION, VERMAJOR etc. are #defined
|
||||
# Ch Like C, but for header files (no VERSION #defines)
|
||||
#
|
||||
make_monolithic() {
|
||||
if [ $# -ne 2 ]
|
||||
|
@ -82,6 +83,9 @@ make_monolithic() {
|
|||
then
|
||||
HASHLINE=1
|
||||
VERDEFINE=1
|
||||
elif [ "$2" == "Ch" ]
|
||||
then
|
||||
HASHLINE=1
|
||||
elif [ "$2" == "none" ]
|
||||
then
|
||||
HASHLINE=0 # dummy command
|
||||
|
@ -261,7 +265,7 @@ else
|
|||
targets="$@"
|
||||
fi
|
||||
|
||||
for func in "${targets}"
|
||||
for func in ${targets}
|
||||
do
|
||||
case ${func} in
|
||||
clean)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
build.c++.app
|
||||
build.c++.lib
|
||||
build.c++.qtapp
|
||||
build.c++.tests
|
||||
build.c.app
|
||||
build.c.lib
|
||||
|
|
|
@ -5,3 +5,7 @@
|
|||
*/
|
||||
|
||||
#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.
|
||||
|
||||
\param name The name of the entity being referred to.
|
||||
\returns The expanded text.
|
||||
\throws UnknownEntity if the entity is unknown.
|
||||
\param[out] value The expanded text.
|
||||
\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,
|
||||
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.
|
||||
|
||||
*/
|
||||
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)
|
||||
: reason(reason)
|
||||
Exception::Exception(const std::wstring& reason, int line, int col)
|
||||
: reason(reason), line(line), col(col)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* Exception::what()
|
||||
const char* Exception::what() const throw()
|
||||
{
|
||||
if(utf8Reason.empty()) utf8Reason = utf8::encode(reason, true);
|
||||
return utf8Reason.c_str();
|
||||
|
@ -23,39 +23,46 @@ const char* Exception::what()
|
|||
|
||||
|
||||
|
||||
NotWellFormed::NotWellFormed(const std::wstring& error)
|
||||
: Exception(format(error)), error(error)
|
||||
NotWellFormed::NotWellFormed(const std::wstring& error, int line, int col)
|
||||
: 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;
|
||||
ost << L"Streamed XML is not well formed:\n"
|
||||
<< error;
|
||||
ost << L"Streamed XML is not well formed:"
|
||||
<< L"\n line : " << line + 1
|
||||
<< L"\n column: " << col + 1
|
||||
<< L"\n reason: " << error;
|
||||
return ost.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
UnknownEntity::UnknownEntity(const std::wstring& name)
|
||||
: Exception(format(name)), name(name)
|
||||
UnknownEntity::UnknownEntity(const std::wstring& name, int line, int col)
|
||||
: 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;
|
||||
ost << L"Encountered an unknown entity named '"
|
||||
<< name
|
||||
<< L"' in the Streamed XML.";
|
||||
ost << L"Encountered an unknown entity in the Streamed XML:"
|
||||
<< L"\n line : " << line + 1
|
||||
<< L"\n column: " << col + 1
|
||||
<< L"\n name : " << name;
|
||||
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.
|
||||
|
||||
*/
|
||||
class Exception {
|
||||
class Exception : public std::exception {
|
||||
public:
|
||||
/*! \brief Constructor.
|
||||
|
||||
\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
|
||||
reporting to the user.
|
||||
|
||||
*/
|
||||
Exception(const std::wstring& reason);
|
||||
Exception(const std::wstring& reason, int line, int col);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~Exception() throw()
|
||||
{ }
|
||||
|
||||
/// Find what caused the error.
|
||||
virtual const char* what();
|
||||
virtual const char* what() const throw();
|
||||
|
||||
/// Reason for the exception.
|
||||
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:
|
||||
std::string utf8Reason;
|
||||
mutable std::string utf8Reason;
|
||||
};
|
||||
|
||||
|
||||
|
@ -45,18 +53,20 @@ private:
|
|||
/// Thrown when XML is not well formed.
|
||||
class NotWellFormed : public Exception {
|
||||
private:
|
||||
static std::wstring format(const std::wstring& error);
|
||||
static std::wstring format(const std::wstring& error, int line, int col);
|
||||
|
||||
public:
|
||||
/*! \brief Constructor.
|
||||
|
||||
\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
|
||||
for the Exception base class.
|
||||
|
||||
*/
|
||||
NotWellFormed(const std::wstring& error);
|
||||
NotWellFormed(const std::wstring& error, int line, int col);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~NotWellFormed() throw()
|
||||
|
@ -71,18 +81,20 @@ public:
|
|||
/// Thrown when an unknown entity is referred to.
|
||||
class UnknownEntity : public Exception {
|
||||
private:
|
||||
static std::wstring format(const std::wstring& name);
|
||||
static std::wstring format(const std::wstring& name, int line, int col);
|
||||
|
||||
public:
|
||||
/*! \brief Constructor.
|
||||
|
||||
\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
|
||||
message for the Exception base class.
|
||||
|
||||
*/
|
||||
UnknownEntity(const std::wstring& name);
|
||||
UnknownEntity(const std::wstring& name, int line, int col);
|
||||
|
||||
/// Destructor.
|
||||
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;
|
||||
state = StateNone;
|
||||
restartCount = 0;
|
||||
line = 0;
|
||||
col = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,7 +61,7 @@ void Parser::feedChar(wchar_t ch)
|
|||
|
||||
#define ERROR(_reason) do { \
|
||||
state = StateError; \
|
||||
throw NotWellFormed(_reason); \
|
||||
throw NotWellFormed(_reason, line, col); \
|
||||
}while(0)
|
||||
if(ch == xmlRestartMarker[restartCount]) {
|
||||
if(++restartCount == 11) {
|
||||
|
@ -84,11 +86,15 @@ void Parser::feedChar(wchar_t ch)
|
|||
skipNextNewline = true;
|
||||
ch = L'\n';
|
||||
c = ClassWhitespace;
|
||||
++line;
|
||||
col = 0;
|
||||
goto doBuffer;
|
||||
|
||||
case 0x2028:
|
||||
ch = L'\n';
|
||||
c = ClassWhitespace;
|
||||
++line;
|
||||
col = 0;
|
||||
break;
|
||||
|
||||
case L' ':
|
||||
|
@ -101,6 +107,8 @@ void Parser::feedChar(wchar_t ch)
|
|||
if(skipNextNewline) return;
|
||||
ch = L'\n';
|
||||
c = ClassWhitespace;
|
||||
++line;
|
||||
col = 0;
|
||||
break;
|
||||
|
||||
case L':':
|
||||
|
@ -155,26 +163,26 @@ doBuffer:
|
|||
break;
|
||||
|
||||
case ClassOpenTag:
|
||||
if(!buffer.empty()) callback->whiteSpace(buffer);
|
||||
state = StateOpen;
|
||||
if(!buffer.empty()) callback->whiteSpace(buffer);
|
||||
buffer.clear();
|
||||
break;
|
||||
|
||||
case ClassEntity:
|
||||
if(expandEntities) {
|
||||
if(!elementDepth) ERROR(L"Entities cannot appear at stream level.");
|
||||
state = StateEntity;
|
||||
if(!buffer.empty()) callback->whiteSpace(buffer);
|
||||
buffer.clear();
|
||||
parsingAttr = false;
|
||||
state = StateEntity;
|
||||
break;
|
||||
}
|
||||
|
||||
// fall through
|
||||
default:
|
||||
if(!elementDepth) ERROR(L"Content cannot appear at stream level.");
|
||||
if(!buffer.empty()) callback->whiteSpace(buffer);
|
||||
state = StateData;
|
||||
if(!buffer.empty()) callback->whiteSpace(buffer);
|
||||
buffer = ch;
|
||||
break;
|
||||
}
|
||||
|
@ -183,16 +191,16 @@ doBuffer:
|
|||
case StateData:
|
||||
switch(c) {
|
||||
case ClassOpenTag:
|
||||
state = StateOpen;
|
||||
callback->content(buffer);
|
||||
buffer.clear();
|
||||
state = StateOpen;
|
||||
break;
|
||||
|
||||
case ClassEntity:
|
||||
state = StateEntity;
|
||||
callback->content(buffer);
|
||||
buffer.clear();
|
||||
parsingAttr = false;
|
||||
state = StateEntity;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -217,9 +225,9 @@ doBuffer:
|
|||
|
||||
case StateCDATA2:
|
||||
if(ch == L'>') {
|
||||
state = StateNone;
|
||||
callback->cdata(buffer);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
} else if(ch == L']') {
|
||||
buffer += ch;
|
||||
} else {
|
||||
|
@ -290,9 +298,9 @@ doBuffer:
|
|||
case StatePI2:
|
||||
if(ch != L'>') ERROR(L"Invalid target for PI");
|
||||
else {
|
||||
state = StateNone;
|
||||
callback->PI(buffer2, L"");
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -303,12 +311,15 @@ doBuffer:
|
|||
|
||||
case StatePI3:
|
||||
if(ch == L'>') {
|
||||
state = StateNone;
|
||||
callback->PI(buffer2, buffer);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
} else if(ch == '?') {
|
||||
buffer += L'?';
|
||||
} else {
|
||||
buffer += L'?';
|
||||
buffer += ch;
|
||||
state = StatePIData;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -343,14 +354,15 @@ doBuffer:
|
|||
else {
|
||||
buffer += L'-';
|
||||
buffer += ch;
|
||||
state = StateComment;
|
||||
}
|
||||
break;
|
||||
|
||||
case StateComment3:
|
||||
if(ch != L'>') ERROR(L"`--' not valid in comments");
|
||||
state = StateNone;
|
||||
callback->comment(buffer);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
break;
|
||||
|
||||
case StateElemName:
|
||||
|
@ -370,10 +382,10 @@ doBuffer:
|
|||
switch(ch) {
|
||||
case L'>':
|
||||
elemStack.push_back(buffer);
|
||||
callback->element(buffer, elemAttrs);
|
||||
state = StateNone;
|
||||
++elementDepth;
|
||||
buffer.clear();
|
||||
callback->element(buffer, elemAttrs);
|
||||
++elementDepth;
|
||||
break;
|
||||
|
||||
case L'/':
|
||||
|
@ -400,9 +412,9 @@ doBuffer:
|
|||
switch(ch) {
|
||||
case L'>':
|
||||
elemStack.push_back(elemName);
|
||||
callback->element(elemName, elemAttrs);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
buffer.clear();
|
||||
callback->element(elemName, elemAttrs);
|
||||
++elementDepth;
|
||||
break;
|
||||
|
||||
|
@ -462,10 +474,10 @@ doBuffer:
|
|||
if(ch == L'/') {
|
||||
state = StateNeedClose;
|
||||
} else if(ch == L'>') {
|
||||
state = StateNone;
|
||||
buffer.clear();
|
||||
callback->element(elemName, elemAttrs);
|
||||
elemStack.push_back(elemName);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
++elementDepth;
|
||||
} else ERROR(L"Invalid character after attribute.");
|
||||
break;
|
||||
|
@ -474,10 +486,10 @@ doBuffer:
|
|||
|
||||
case StateNeedClose:
|
||||
if(ch != L'>') ERROR(L"Stray `/' in open tag.");
|
||||
state = StateNone;
|
||||
buffer.clear();
|
||||
callback->element(elemName, elemAttrs);
|
||||
callback->closeTag(elemName);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
break;
|
||||
|
||||
case StateClose:
|
||||
|
@ -501,9 +513,9 @@ doBuffer:
|
|||
if(ch != L'>') ERROR(L"Invalid character in close tag name.");
|
||||
if(elemStack.back() != buffer) ERROR(L"Mismatched close tag.");
|
||||
elemStack.pop_back();
|
||||
callback->closeTag(buffer);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
buffer.clear();
|
||||
callback->closeTag(buffer);
|
||||
--elementDepth;
|
||||
}
|
||||
break;
|
||||
|
@ -513,9 +525,9 @@ doBuffer:
|
|||
if(ch != L'>') ERROR(L"Invalid data in close tag.");
|
||||
if(elemStack.back() != elemName) ERROR(L"Mismatched close tag.");
|
||||
elemStack.pop_back();
|
||||
callback->closeTag(elemName);
|
||||
buffer.clear();
|
||||
state = StateNone;
|
||||
buffer.clear();
|
||||
callback->closeTag(elemName);
|
||||
--elementDepth;
|
||||
break;
|
||||
|
||||
|
@ -566,6 +578,7 @@ doBuffer:
|
|||
break;
|
||||
}
|
||||
#undef ERROR
|
||||
++col;
|
||||
}
|
||||
|
||||
|
||||
|
@ -577,9 +590,16 @@ std::wstring Parser::entityRef(const std::wstring& ent)
|
|||
if(ent == L"apos") return L"'";
|
||||
if(ent == L"lt") 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;
|
||||
int elementDepth, xmlCount, restartCount;
|
||||
|
||||
// for reporting errors
|
||||
int line, col;
|
||||
|
||||
public:
|
||||
/*! \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 <utf8>
|
||||
#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.
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
|
|
|
@ -31,7 +31,7 @@ then
|
|||
echo " Compiling"
|
||||
|
||||
SONAME="${libStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}"
|
||||
do_cmd ${CXX} ${CFLAGS} -shared -fpic -o "${libStreamedXML}" \
|
||||
do_cmd ${CXX} ${CFLAGS} -Iobj -shared -fpic -o "${libStreamedXML}" \
|
||||
-Wl,-soname,${SONAME} \
|
||||
${SRC} ${SO_EXTRA} || return 1
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ MONOLITHIC_TESTS="src/libStreamedXML/build.lib src/libStreamedXML/build.monolith
|
|||
if [ -z "${libStreamedXML_MONOLITHIC}" ]
|
||||
then
|
||||
MONOLITHIC_SOURCE="$(echo src/libStreamedXML/{TopHeader,ForwardDeclare,Exceptions,Callback,Parser,Decoder,BottomHeader}.h)"
|
||||
make_monolithic ${HDR} C || return 1
|
||||
make_monolithic ${HDR} Ch || return 1
|
||||
|
||||
MONOLITHIC_SOURCE="$(echo src/libStreamedXML/{TopSource,Exceptions,Parser,Decoder}.cpp)"
|
||||
make_monolithic ${SRC} C || return 1
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# be bumped on a binary-incompatible release. They are both single
|
||||
# integers.
|
||||
SOMAJOR=0
|
||||
SOMINOR=0
|
||||
SOMINOR=1
|
||||
|
||||
# SOMICRO is bumped every time there is a binary-compatible release.
|
||||
SOMICRO=0
|
||||
SOMICRO=3
|
||||
|
|
Loading…
Reference in New Issue