diff --git a/README b/README index 0aa0cf7..b186998 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -libStreamedXML +libStreamedXML http://www.lwithers.me.uk/projects/libStreamedXML/ ======================================================================== (c)2006, Laurence Withers, . 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++/ diff --git a/make.sh b/make.sh index 856f0d0..f3f44d8 100755 --- a/make.sh +++ b/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) diff --git a/scripts/.gitignore b/scripts/.gitignore index ce33425..a540f48 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,5 +1,6 @@ build.c++.app build.c++.lib +build.c++.qtapp build.c++.tests build.c.app build.c.lib diff --git a/src/libStreamedXML/BottomHeader.h b/src/libStreamedXML/BottomHeader.h index 4bbc273..fbf44c3 100644 --- a/src/libStreamedXML/BottomHeader.h +++ b/src/libStreamedXML/BottomHeader.h @@ -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 +*/ diff --git a/src/libStreamedXML/Callback.h b/src/libStreamedXML/Callback.h index 78f2add..5ed5617 100644 --- a/src/libStreamedXML/Callback.h +++ b/src/libStreamedXML/Callback.h @@ -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 +*/ diff --git a/src/libStreamedXML/Decoder.cpp b/src/libStreamedXML/Decoder.cpp index 2a0d6fb..4eecb09 100644 --- a/src/libStreamedXML/Decoder.cpp +++ b/src/libStreamedXML/Decoder.cpp @@ -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 +*/ diff --git a/src/libStreamedXML/Decoder.h b/src/libStreamedXML/Decoder.h index 6f220bb..d62a93b 100644 --- a/src/libStreamedXML/Decoder.h +++ b/src/libStreamedXML/Decoder.h @@ -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 +*/ diff --git a/src/libStreamedXML/Exceptions.cpp b/src/libStreamedXML/Exceptions.cpp index 68c079b..ee909e6 100644 --- a/src/libStreamedXML/Exceptions.cpp +++ b/src/libStreamedXML/Exceptions.cpp @@ -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 +*/ diff --git a/src/libStreamedXML/Exceptions.h b/src/libStreamedXML/Exceptions.h index 398c51d..fbabf73 100644 --- a/src/libStreamedXML/Exceptions.h +++ b/src/libStreamedXML/Exceptions.h @@ -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 +*/ diff --git a/src/libStreamedXML/ForwardDeclare.h b/src/libStreamedXML/ForwardDeclare.h index d3ad008..113253c 100644 --- a/src/libStreamedXML/ForwardDeclare.h +++ b/src/libStreamedXML/ForwardDeclare.h @@ -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 +*/ diff --git a/src/libStreamedXML/Parser.cpp b/src/libStreamedXML/Parser.cpp index f6efd56..ee6f0f6 100644 --- a/src/libStreamedXML/Parser.cpp +++ b/src/libStreamedXML/Parser.cpp @@ -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 +*/ diff --git a/src/libStreamedXML/Parser.h b/src/libStreamedXML/Parser.h index 78f1493..b0567fc 100644 --- a/src/libStreamedXML/Parser.h +++ b/src/libStreamedXML/Parser.h @@ -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 +*/ diff --git a/src/libStreamedXML/TopHeader.h b/src/libStreamedXML/TopHeader.h index 837f7c2..4c33456 100644 --- a/src/libStreamedXML/TopHeader.h +++ b/src/libStreamedXML/TopHeader.h @@ -14,3 +14,7 @@ #include #include #include +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libStreamedXML/TopSource.cpp b/src/libStreamedXML/TopSource.cpp index 2ef09e7..5a08e5c 100644 --- a/src/libStreamedXML/TopSource.cpp +++ b/src/libStreamedXML/TopSource.cpp @@ -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 +*/ diff --git a/src/libStreamedXML/build.lib b/src/libStreamedXML/build.lib index b685b96..086ab44 100644 --- a/src/libStreamedXML/build.lib +++ b/src/libStreamedXML/build.lib @@ -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 diff --git a/src/libStreamedXML/build.monolithic b/src/libStreamedXML/build.monolithic index 2a05e4b..cc582d4 100644 --- a/src/libStreamedXML/build.monolithic +++ b/src/libStreamedXML/build.monolithic @@ -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 diff --git a/src/libStreamedXML/soversion b/src/libStreamedXML/soversion index b706c89..c4c84a8 100644 --- a/src/libStreamedXML/soversion +++ b/src/libStreamedXML/soversion @@ -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 diff --git a/version b/version index 1eaadc1..a0ec19b 100644 --- a/version +++ b/version @@ -11,8 +11,8 @@ # expected to be in 'major.minor.micro' format. It can optionally be # suffixed with a string. VERMAJOR=1 -VERMINOR=1 -VERMICRO=0 +VERMINOR=2 +VERMICRO=8 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4;