From 44147acacf39e27b0ee568d7abbc0e705f07dcc2 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Mon, 7 Aug 2006 11:06:31 +0100 Subject: [PATCH 01/18] 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. --- src/libStreamedXML/BottomHeader.h | 4 ++++ src/libStreamedXML/Callback.h | 15 +++++++++---- src/libStreamedXML/Decoder.cpp | 4 ++++ src/libStreamedXML/Decoder.h | 4 ++++ src/libStreamedXML/Exceptions.cpp | 35 +++++++++++++++++------------ src/libStreamedXML/Exceptions.h | 34 ++++++++++++++++++++-------- src/libStreamedXML/ForwardDeclare.h | 4 ++++ src/libStreamedXML/Parser.cpp | 20 +++++++++++++++-- src/libStreamedXML/Parser.h | 7 ++++++ src/libStreamedXML/TopHeader.h | 4 ++++ src/libStreamedXML/TopSource.cpp | 4 ++++ 11 files changed, 106 insertions(+), 29 deletions(-) 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..f91b79a 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':': @@ -566,6 +574,7 @@ doBuffer: break; } #undef ERROR + ++col; } @@ -577,9 +586,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 +*/ From 4eec490403d7130f1d22808ac5d3f42b1873987c Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Mon, 7 Aug 2006 11:07:35 +0100 Subject: [PATCH 02/18] Bump versions. --- src/libStreamedXML/soversion | 2 +- version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libStreamedXML/soversion b/src/libStreamedXML/soversion index b706c89..f0f1c97 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 diff --git a/version b/version index 1eaadc1..b0f29f4 100644 --- a/version +++ b/version @@ -11,7 +11,7 @@ # expected to be in 'major.minor.micro' format. It can optionally be # suffixed with a string. VERMAJOR=1 -VERMINOR=1 +VERMINOR=2 VERMICRO=0 VEREXTRA="" From dc6a4cf4309c841d621352ee14c5b2de82aceff3 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Mon, 7 Aug 2006 12:51:11 +0100 Subject: [PATCH 03/18] Fix bug: in a PI such as , we got into an incorrect state on the second ?. This is now properly handled. --- src/libStreamedXML/Parser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libStreamedXML/Parser.cpp b/src/libStreamedXML/Parser.cpp index f91b79a..5047ceb 100644 --- a/src/libStreamedXML/Parser.cpp +++ b/src/libStreamedXML/Parser.cpp @@ -314,9 +314,12 @@ doBuffer: callback->PI(buffer2, buffer); buffer.clear(); state = StateNone; + } else if(ch == '?') { + buffer += L'?'; } else { buffer += L'?'; buffer += ch; + state = StatePIData; } break; From 4533df294703622501a3a9618d2ed1068b7b9034 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Tue, 8 Aug 2006 12:19:08 +0100 Subject: [PATCH 04/18] Add in libCStreamedXML and a test program for it. --- src/ctests/.params | 1 + src/ctests/build.default | 3 + src/ctests/build.tests | 43 ++ src/ctests/cCallback.c | 137 +++++ src/ctests/template | 35 ++ src/libCStreamedXML/.functions.h.swp | Bin 0 -> 12288 bytes src/libCStreamedXML/.params | 1 + src/libCStreamedXML/BottomHeader.h | 14 + src/libCStreamedXML/TopHeader.h | 32 ++ src/libCStreamedXML/TopSource.c | 20 + src/libCStreamedXML/buffer.c | 100 ++++ src/libCStreamedXML/build.default | 1 + src/libCStreamedXML/build.install | 1 + src/libCStreamedXML/build.install-lib | 36 ++ src/libCStreamedXML/build.lib | 51 ++ src/libCStreamedXML/build.monolithic | 21 + src/libCStreamedXML/defaults.c | 79 +++ src/libCStreamedXML/functions.h | 102 ++++ src/libCStreamedXML/parser.c | 692 ++++++++++++++++++++++++++ src/libCStreamedXML/pkgconf.in | 21 + src/libCStreamedXML/soversion | 17 + src/libCStreamedXML/types.h | 320 ++++++++++++ 22 files changed, 1727 insertions(+) create mode 100644 src/ctests/.params create mode 100644 src/ctests/build.default create mode 100644 src/ctests/build.tests create mode 100644 src/ctests/cCallback.c create mode 100644 src/ctests/template create mode 100644 src/libCStreamedXML/.functions.h.swp create mode 100644 src/libCStreamedXML/.params create mode 100644 src/libCStreamedXML/BottomHeader.h create mode 100644 src/libCStreamedXML/TopHeader.h create mode 100644 src/libCStreamedXML/TopSource.c create mode 100644 src/libCStreamedXML/buffer.c create mode 100644 src/libCStreamedXML/build.default create mode 100644 src/libCStreamedXML/build.install create mode 100644 src/libCStreamedXML/build.install-lib create mode 100644 src/libCStreamedXML/build.lib create mode 100644 src/libCStreamedXML/build.monolithic create mode 100644 src/libCStreamedXML/defaults.c create mode 100644 src/libCStreamedXML/functions.h create mode 100644 src/libCStreamedXML/parser.c create mode 100644 src/libCStreamedXML/pkgconf.in create mode 100644 src/libCStreamedXML/soversion create mode 100644 src/libCStreamedXML/types.h diff --git a/src/ctests/.params b/src/ctests/.params new file mode 100644 index 0000000..5dcd0de --- /dev/null +++ b/src/ctests/.params @@ -0,0 +1 @@ +c tests ctests libCStreamedXML diff --git a/src/ctests/build.default b/src/ctests/build.default new file mode 100644 index 0000000..183fd69 --- /dev/null +++ b/src/ctests/build.default @@ -0,0 +1,3 @@ +source src/ctests/build.tests +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: expandtab:ts=4:sw=4 diff --git a/src/ctests/build.tests b/src/ctests/build.tests new file mode 100644 index 0000000..ebf1a82 --- /dev/null +++ b/src/ctests/build.tests @@ -0,0 +1,43 @@ +# These are external variables, and shouldn't clash with anything else +# ctests_BUILT +# + +build_target libCStreamedXML || return 1 + +if [ -z ${ctests_BUILT} ] +then + LIBS="${libCStreamedXML} " + EXTRAS="" + + echo "Building test programs..." + do_cmd mkdir -p obj/tests || return 1 + + for SRC in src/ctests/*.c + do + TEST="obj/tests/$(basename ${SRC} | sed -e 's,.c$,,')" + MODIFIED=0 + for file in ${LIBS} ${SRC} src/ctests/build.tests + do + if [ ${file} -nt ${TEST} ] + then + MODIFIED=1 + break + fi + done + + if [ ${MODIFIED} -ne 0 ] + then + do_cmd ${CC} -Iobj ${CFLAGS} -o ${TEST} ${SRC} ${LIBS} ${EXTRAS} || return 1 + print_success "Built ${TEST}" + else + print_success "${TEST} is up to date" + fi + done + + print_success "All tests built" + + ctests_BUILT=1 +fi + +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: expandtab:ts=4:sw=4 diff --git a/src/ctests/cCallback.c b/src/ctests/cCallback.c new file mode 100644 index 0000000..0540df3 --- /dev/null +++ b/src/ctests/cCallback.c @@ -0,0 +1,137 @@ +/* libStreamedXML/src/ctests/cCallback.c + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#include "StreamedXML.h" + +#include +#include + + + +int echo_whiteSpace(const struct csxml* ctx, const char* ws) +{ + (void)ctx; + printf("Whitespace: ``%s''\n", ws); + return 0; +} + +int echo_content(const struct csxml* ctx, const char* data) +{ + (void)ctx; + printf("Content: ``%s''\n", data); + return 0; +} + +int echo_cdata(const struct csxml* ctx, const char* data) +{ + (void)ctx; + printf("CDATA: ``%s''\n", data); + return 0; +} + +int echo_streamRestart(const struct csxml* ctx, const char* data) +{ + (void)ctx; + printf("Stream restart marker: ``%s''\n", data); + return 0; +} + +int echo_PI(const struct csxml* ctx, const char* target, const char* data) +{ + (void)ctx; + printf("PI: target ``%s'', data ", target); + if(data) printf("``%s''\n", data); + else printf("not specified\n"); + return 0; +} + +int echo_comment(const struct csxml* ctx, const char* data) +{ + (void)ctx; + printf("Comment: ``%s''\n", data); + return 0; +} + +int echo_element(const struct csxml* ctx, const char* elemName, int numAttrs) +{ + int i; + + printf("Open tag: <%s> (%d attributes)\n", elemName, numAttrs); + for(i = 0; i < numAttrs; ++i) printf(" %s='%s'\n", ctx->elemAttrNames.data[i].data, ctx->elemAttrVals.data[i].data); + return 0; +} + +int echo_closeTag(const struct csxml* ctx, const char* elemName) +{ + (void)ctx; + printf("Close tag: \n", elemName); + return 0; +} + +const char* echo_entityRef(const struct csxml* ctx, const char* ent) +{ + (void)ctx; + printf("Entity reference: ``%s''\n", ent); + return 0; +} + + + +int main(int argc, char* argv[]) +{ + FILE* fp = 0; + char buf[1024]; + size_t amt; + struct csxml* ctx = 0; + + if(argc == 2 && !strcmp(argv[1], "--print-summary")) { + printf("{C library} Tests the callback functions.\n"); + return 0; + } + + if(argc != 2) { + fprintf(stderr, "Expecting filename.\n"); + return 1; + } + + fp = fopen(argv[1], "r"); + if(!fp) { + fprintf(stderr, "Error opening '%s' for input.\n", argv[1]); + return 1; + } + + ctx = csxml_newParser(); + if(!ctx) { + fprintf(stderr, "Couldn't allocate a new parser.\n"); + return 1; + } + + ctx->whiteSpace = echo_whiteSpace; + ctx->content = echo_content; + ctx->cdata = echo_cdata; + ctx->streamRestart = echo_streamRestart; + ctx->PI = echo_PI; + ctx->comment = echo_comment; + ctx->element = echo_element; + ctx->closeTag = echo_closeTag; + ctx->entityRef = echo_entityRef; + + while(!feof(fp)) { + amt = fread(buf, 1, sizeof(buf), fp); + csxml_feedData(ctx, buf, amt); + } + + csxml_freeParser(ctx); + fclose(fp); + + return 0; +} + +/* 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/ctests/template b/src/ctests/template new file mode 100644 index 0000000..a829314 --- /dev/null +++ b/src/ctests/template @@ -0,0 +1,35 @@ +/* libStreamedXML/src/ctests/???.c + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#include "StreamedXML.h" + +#include + + + +int main(int argc, char* argv[]) +{ + if(argc == 2 && !strcmp(argv[1], "--print-summary")) { + printf("One line summary.\n"); + return 0; + } + + if(argc == 1) { + // empty argument list + } + + int ret = 0; + + // TODO + + return ret; +} + +/* 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/libCStreamedXML/.functions.h.swp b/src/libCStreamedXML/.functions.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..9dd2f80f06035a47e75c0167891908de2cfdae6e GIT binary patch literal 12288 zcmeHN&yO6%6)u8FNX(BYa7r!@!ePCcnOzf$M7EGf3^A6By%?K>#FAChT|HfFcU7yZ zdS}NFatJ3Rat`FDatT-hkv{>2D1k`%p@b5c>cnkO~kO7B)Ki`gbfja_7N5uPIVe`I(9;Atdp(cRUOK# zqo8&JsZJ1mwsN9!Hc{TwS|W>L zER*d4Dd#{1W(9SGch785*r`efG_Kine$-xYYK)&-ylT~mF62sF*#82%u1HDn!L-RF zD95faEo0ou+9sPtM@DoyBWYTbu(2|UtqrELIXu1gwJacwSW=eEIGwG_F_yy$<5^H3 z&qk`%Xg(q=uaXt&7r7gD8Mb?oRBXpegd+5^GX_Yl&;B)0|u9&5~0oy9< zPntF@mb_uE;2*v@5QwbI*gT{gZknwGjYHy47P71gxOD)*aofmGq?*ZvqdH&%ql1=3 z6W#$yPA*$dax%6_om{3gQ-Q`x8S03=5gX^(&xU6Qp3no9ilQkYRG<#C^D5g<$KD#k z#Fn4hY#Tc@kHj}4F`S`Dh!l*3+8IxqBVmy^HagpFv6zcAm=_!9)EOC+jY?x;@j&wm z^KNVaueCv9X_Pafz}&3n?;=3hGesU|02gmuNGp$(xz5y2UTPs zAATVJwSm@Lnme?Vn5Hg@A+n&<2DO-SGO%F4rA89*s5PH;3;B&Tb`aZ5$VpQ&UCv`3 zJ<`x|Z!W)O$N2i8Sb8^b;`RgwBijtj*Ulrkha4;@@0V3$=36T~?V57ed8ktl7AeC!o6 zuTfDmO0`coU{NS4={<;!M;Pb~#VQFmgtGSFyxQ#l`6j>^91^`NUQEY#g%(vgje%IS*2M6`m!@bq;n&#QO*AWR7PIdC&NFN}F%tDW zXL(U8h!u*3sf#gO48$Vxb;8|oQ7$=gwl@t6DG|L|jQ*D`W8ph1 z8GQ>=n8sGu+caU)k?&j=Eb>TMn=oT-4mXFE8Wl&pFd~2~Ewm5#P$3!NsIlDkE-dmC zKC)4?R>~O{?IurM>Vj-eWOWy-aW(F-D~d(4d3R!p$0?(xt)ENk5XtGgJTnncfzt!xgmWsb6P-M__0;LJr{WQ#w2qaNg+%fpnKp1j zcBSV$D|7<-(MkBFwdBbCo0|^|=!`^`vEF{Wxq?5U^Qusi6%?Hn^20$qb@n2i+B!3$ aCt!J|3xzfKB))o${-CS%VOF8X=Hfq!?3wWZ literal 0 HcmV?d00001 diff --git a/src/libCStreamedXML/.params b/src/libCStreamedXML/.params new file mode 100644 index 0000000..eca3504 --- /dev/null +++ b/src/libCStreamedXML/.params @@ -0,0 +1 @@ +c lib libCStreamedXML StreamedXML.h diff --git a/src/libCStreamedXML/BottomHeader.h b/src/libCStreamedXML/BottomHeader.h new file mode 100644 index 0000000..072d08e --- /dev/null +++ b/src/libCStreamedXML/BottomHeader.h @@ -0,0 +1,14 @@ +/* libCStreamedXML/src/clib/BottomHeader.h + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#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/libCStreamedXML/TopHeader.h b/src/libCStreamedXML/TopHeader.h new file mode 100644 index 0000000..729d936 --- /dev/null +++ b/src/libCStreamedXML/TopHeader.h @@ -0,0 +1,32 @@ +/* libCStreamedXML/src/libCStreamedXML/TopHeader.h + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#ifndef HEADER_libCStreamedXML +#define HEADER_libCStreamedXML + +// standard includes, or includes needed for type declarations +#include + +/*! \defgroup libCStreamedXML libCStreamedXML interface. + +libCStreamedXML is a C library for parsing Streamed XML data. It is somewhat simpler than the C++ +library (it only parses ASCII data, not Unicode data). In future, the API could be extended to +use only fixed-size buffers, and not to call malloc() at all. This would be advantageous for small +embedded systems (e.g. PICs). + +To parse Streamed XML, you must first create a parser context object with csxml_newParser(). Then +you set up the returned object by changing options and callback functions. Once set up correctly, +pass in data using the csxml_feedChar() and csxml_feedData() functions. Finally, free the parser +object with csxml_freeParser(). + +*/ +/*!@{*/ + +/* 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/libCStreamedXML/TopSource.c b/src/libCStreamedXML/TopSource.c new file mode 100644 index 0000000..90d401c --- /dev/null +++ b/src/libCStreamedXML/TopSource.c @@ -0,0 +1,20 @@ +/* libCStreamedXML/src/libCStreamedXMLlibCStreamedXML/TopSource.c + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + +#include "StreamedXML.h" + +// Below are all the includes used throughout the library. +#include +#include +#include + +//#define DEBUG_STATE_MACHINE + +/* 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/libCStreamedXML/buffer.c b/src/libCStreamedXML/buffer.c new file mode 100644 index 0000000..10cab8a --- /dev/null +++ b/src/libCStreamedXML/buffer.c @@ -0,0 +1,100 @@ +/* libCStreamedXML/src/libCStreamedXML/buffer.c + * + * (c)2006, Laurence Withers. Released under the GNU GPL. See file + * COPYING for more information / terms of license. +*/ + +static int do_realloc(struct csxml* ctx, struct csxml_buf* buf) +{ + char* n = realloc(buf->data, buf->size << 1); + if(!n) { + ctx->outOfMemory(ctx, buf->size << 1); + return -1; + } + + buf->size <<= 1; + buf->data = n; + return 0; +} + +static int buffer_copy(struct csxml* ctx, struct csxml_buf* dest, const struct csxml_buf* src) +{ + while(dest->size <= src->len) if(do_realloc(ctx, dest)) return -1; + strcpy(dest->data, src->data); + dest->len = src->len; + return 0; +} + +static int buffer_strcat(struct csxml* ctx, struct csxml_buf* dest, const char* src) +{ + size_t req = strlen(src) + dest->len; + while(req >= dest->size) if(do_realloc(ctx, dest)) return -1; + strcat(dest->data, src); + return 0; +} + +static int buffer_init(struct csxml* ctx, struct csxml_buf* buf) +{ + memset(buf, 0, sizeof(buf)); + buf->size = 256; + buf->data = malloc(buf->size); + if(!buf->data) { + ctx->outOfMemory(ctx, buf->size); + return -1; + } + return 0; +} + +static void buffer_free(struct csxml_buf* buf) +{ + free(buf->data); + memset(buf, 0, sizeof(struct csxml_buf)); +} + +static int do_realloc2(struct csxml* ctx, struct csxml_list* list) +{ + size_t i, newlen = list->size ? (list->size << 1) : 4; + struct csxml_buf* n = realloc(list->data, newlen * sizeof(struct csxml_buf)); + if(!n) { + ctx->outOfMemory(ctx, newlen * sizeof(struct csxml_buf)); + return -1; + } + + memset(n + list->size * sizeof(struct csxml_buf), 0, newlen * sizeof(struct csxml_buf)); + for(i = 0; i < newlen; ++i) { + if(buffer_init(ctx, n + list->size + i)) return -1; + } + + list->size = newlen; + list->data = n; + return 0; +} + +static int list_push(struct csxml* ctx, struct csxml_list* list, struct csxml_buf* buf) +{ + if((list->size == list->len) && do_realloc2(ctx, list)) return -1; + if(buffer_copy(ctx, list->data + list->len, buf)) return -1; + ++list->len; + return 0; +} + +static struct csxml_buf* list_pop(struct csxml_list* list) +{ + return list->data + --list->len; +} + +static void list_free(struct csxml_list* list) +{ + size_t i; + + for(i = 0; i < list->size; ++i) buffer_free(list->data + i); + free(list->data); + memset(list, 0, sizeof(struct csxml_list)); +} + + + +/* 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/libCStreamedXML/build.default b/src/libCStreamedXML/build.default new file mode 100644 index 0000000..a24840e --- /dev/null +++ b/src/libCStreamedXML/build.default @@ -0,0 +1 @@ +source src/libCStreamedXML/build.lib diff --git a/src/libCStreamedXML/build.install b/src/libCStreamedXML/build.install new file mode 100644 index 0000000..a8df5b5 --- /dev/null +++ b/src/libCStreamedXML/build.install @@ -0,0 +1 @@ +source src/libCStreamedXML/build.install-lib diff --git a/src/libCStreamedXML/build.install-lib b/src/libCStreamedXML/build.install-lib new file mode 100644 index 0000000..beec81b --- /dev/null +++ b/src/libCStreamedXML/build.install-lib @@ -0,0 +1,36 @@ +build_target libCStreamedXML + +# make paths (this is for Gentoo in particular) +build_dir_tree "${LIBDIR}" || return 1 +build_dir_tree "${PKGCONFDIR}" || return 1 +build_dir_tree "${INCLUDEDIR}" || return 1 + +# install library +echo "Installing libraries into '${LIBDIR}'" +install_file ${libCStreamedXML} ${LIBDIR} 0755 || return 1 +BASE="${libCStreamedXML_BASE}.so" +MAJOR="${BASE}.${SOMAJOR}" +MINOR="${MAJOR}.${SOMINOR}" +MICRO="${MINOR}.${SOMICRO}" +install_symlink "${MINOR}" "${MICRO}" "${LIBDIR}" +install_symlink "${MAJOR}" "${MINOR}" "${LIBDIR}" +install_symlink "${BASE}" "${MAJOR}" "${LIBDIR}" + +# install header +echo "Installing header file '${libCStreamedXML_HEADER}' into ${INCLUDEDIR}" +install_header ${libCStreamedXML_HEADER} ${INCLUDEDIR} 0644 || return 1 + +# install pkgconfig file +echo "Installing package config file into ${PKGCONFDIR}" +PKGCONFFILE=${PKGCONFDIR}/libCStreamedXML.pc +do_cmd rm -f ${PKGCONFFILE} +do_cmd_redir ${PKGCONFFILE} sed \ + -e "s,@VERSION@,${VERSION}," \ + -e "s,@LIBDIR@,${FINALLIBDIR}," \ + -e "s,@INCLUDEDIR@,${FINALINCLUDEDIR}," \ + src/libCStreamedXML/pkgconf.in +do_cmd chmod 0644 ${PKGCONFFILE} +print_success "Done" + +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/build.lib b/src/libCStreamedXML/build.lib new file mode 100644 index 0000000..5d316e8 --- /dev/null +++ b/src/libCStreamedXML/build.lib @@ -0,0 +1,51 @@ +# These are external variables, and shouldn't clash with anything else +# libCStreamedXML +# libCStreamedXML_BUILT +# libCStreamedXML_HEADER +# libCStreamedXML_BASE + +if [ -z ${libCStreamedXML_BUILT} ] +then + libCStreamedXML_BASE=libCStreamedXML + source src/libCStreamedXML/soversion + + libCStreamedXML="obj/${libCStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}.${SOMICRO}" + SO_EXTRA="-lc" # @TODO@ libs, cflags + + echo "Building library ${libCStreamedXML}..." + + do_cmd source src/libCStreamedXML/build.monolithic || return 1 + + MODIFIED=0 + for test in ${MONOLITHIC_TESTS} ${HDR} ${SRC} + do + if [ ${test} -nt ${libCStreamedXML} ] + then + MODIFIED=1 + break + fi + done + + if [ ${MODIFIED} -ne 0 ] + then + echo " Compiling" + + SONAME="${libCStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}" + do_cmd ${CC} ${CFLAGS} -shared -fpic -o "${libCStreamedXML}" \ + -Wl,-soname,${SONAME} \ + ${SRC} ${SO_EXTRA} || return 1 + + # make tests work + do_cmd ln -sf $(basename ${libCStreamedXML}) obj/${SONAME} || return 1 + + print_success "Library built" + else + print_success "Library up to date" + fi + + libCStreamedXML_BUILT=1 + libCStreamedXML_HEADER=${HDR} + +fi +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/build.monolithic b/src/libCStreamedXML/build.monolithic new file mode 100644 index 0000000..a6027c4 --- /dev/null +++ b/src/libCStreamedXML/build.monolithic @@ -0,0 +1,21 @@ +# These are external variables, and shouldn't clash with anything else +# libCStreamedXML_MONOLITHIC + +SRC="obj/libCStreamedXML.c" +HDR="obj/StreamedXML.h" + +MONOLITHIC_TESTS="src/libCStreamedXML/build.lib src/libCStreamedXML/build.monolithic" + +if [ -z "${libCStreamedXML_MONOLITHIC}" ] +then + MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopHeader,types,functions,BottomHeader}.h)" + make_monolithic ${HDR} C || return 1 + + MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopSource,buffer,defaults,parser}.c)" + make_monolithic ${SRC} C || return 1 + + libCStreamedXML_MONOLITHIC=1 + MONOLITHIC_DOC="${MONOLITHIC_DOC} ${HDR}" +fi +# kate: replace-trailing-space-save true; space-indent true; tab-width 4; +# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/defaults.c b/src/libCStreamedXML/defaults.c new file mode 100644 index 0000000..b4d147e --- /dev/null +++ b/src/libCStreamedXML/defaults.c @@ -0,0 +1,79 @@ +/* libCStreamedXML/src/libCStreamedXML/defaults.c + * + * (c)2006, Laurence Withers. Released under the GNU GPL. See file + * COPYING for more information / terms of license. +*/ + +static void default_notWellFormed(const struct csxml* ctx, const char* reason) +{ + fprintf(stderr, "Streamed XML is not well formed.\n Line : %d\n Col : %d\n Reason: %s\n", + ctx->line + 1, ctx->col + 1, reason); +} + + + +static void default_outOfMemory(const struct csxml* ctx, size_t amount) +{ + (void)ctx; + fprintf(stderr, "Streamed XML parser: out of memory allocating %lu bytes\n", amount); +} + + + +static void default_unknownEntity(const struct csxml* ctx, const char* ent) +{ + fprintf(stderr, "Unknown entity referenced in Streamed XML.\n Line: %d\n Col : %d\n Name: %s\n", + ctx->line + 1, ctx->col + 1, ent); +} + + + +static int default_discard(const struct csxml* ctx, const char* x) +{ + (void)ctx; + (void)x; + return 0; +} + + + +static int default_cdata(const struct csxml* ctx, const char* data) +{ + return ctx->content(ctx, data); +} + + + +static int default_discardPI(const struct csxml* ctx, const char* target, const char* data) +{ + (void)ctx; + (void)target; + (void)data; + return 0; +} + + + +static int default_discardElem(const struct csxml* ctx, const char* elemName, int numAttrs) +{ + (void)ctx; + (void)elemName; + (void)numAttrs; + return 0; +} + + + +static const char* default_discardEnt(const struct csxml* ctx, const char* ent) +{ + (void)ctx; + (void)ent; + return 0; +} + + + +/* 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/libCStreamedXML/functions.h b/src/libCStreamedXML/functions.h new file mode 100644 index 0000000..9075ba9 --- /dev/null +++ b/src/libCStreamedXML/functions.h @@ -0,0 +1,102 @@ +/* libCStreamedXML/src/libCStreamedXML/types.h + * + * (c)2006, Laurence Withers. Released under the GNU GPL. See file + * COPYING for more information / terms of license. +*/ + + + +/*! \brief Allocate and set up a new parser object. + +\retval 0 on error (see \a errno). +\returns Pointer to newly-allocated parser object. + +Call this function to obtain a parser context object. The object is initially populated with +sensible defaults (\a expandEntities is 1, the error callback functions print messages to stderr, +the data callback functions discard the data, etc.). + +*/ +struct csxml* csxml_newParser(); + + + +/*! \brief Free an existing parser object. + +\param ctx The object to free (may be 0). + +Frees a parser object and all of its associated data structures (strings, lists, etc.). + +*/ +void csxml_freeParser(struct csxml* ctx); + + + +/*! \brief Parse a character. + +\param ctx Parser context. +\param ch Character to parse. +\retval 0 on success. +\retval -1 on XML error. +\retval (non-0) if any callback function signals an error. + +This function parses a single character. It will generate callbacks as appropriate. If one of the +callback functions returns a non-zero value, that value is returned from this function and the +object is put into an error state. If the streamed XML is not well formed, or some other parsing +error occurs, -1 will be returned and the object will be put into an error state. + +Once in an error state, the function will simply discard data passed to it and return 0. However, +a lower-level parser is still running and is capable of matching stream restart markers, allowing +the parser to be reset. + +*/ +int csxml_feedChar(struct csxml* ctx, char ch); + + + +/*! \brief Look up an entity. + +\param ctx Parser context. +\param ent Entity name. +\retval 0 on error. +\returns Pointer to null-terminated string of expanded entity text. + +This function is called to dereference entities. It handles the standard entities itself, and chains +on to the entityRef callback of the parser if needed. If the entity is not found, it calls the +unknownEntity callback and returns 0. + +*/ +const char* csxml_entityRef(struct csxml* ctx, const char* ent); + + + +/*! \brief Reset parser. + +\param ctx Parser context. + +This function will reset the parser into its initial state, as though no data had yet been +encountered. This is called after stream restart markers for example. + +*/ +void csxml_reset(struct csxml* ctx); + + + + +/*! \brief Parse a block of data. + +\param ctx Parser context. +\param data Pointer to block of data. +\param amt Number of bytes to parse. + +This function will parse each character in the block of data. If an error is encountered, the usual +process (callback, error state) is followed, but this function will continue to feed in data. The +idea is that you continue to feed in data from your data source, which might have a restart marker +(at which point the parsing will once again continue). + +*/ +void csxml_feedData(struct csxml* ctx, const char* data, size_t amt); + +/* 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/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c new file mode 100644 index 0000000..cf1fcfb --- /dev/null +++ b/src/libCStreamedXML/parser.c @@ -0,0 +1,692 @@ +/* libCStreamedXML/src/libCStreamedXML/parser.c + * + * (c)2006, Laurence Withers. Released under the GNU GPL. See file + * COPYING for more information / terms of license. +*/ + +//#define DEBUG_STATE_MACHINE + +#ifdef DEBUG_STATE_MACHINE +#include +#endif + +#include +#include +#include + + + +enum csxml_State { + StateNone, // at element or stream level + StateRestartMarker, // after ', '?' + ClassOther, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // '@', 'A'--'C' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'D'--'G' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'H'--'K' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'L'--'O' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'P'--'S' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'T'--'W' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassOther, // 'X'--'Z', '[' + ClassOther, ClassOther, ClassOther, ClassNameStartChar, // '\\', ']', '^', '_' + ClassOther, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // '`', 'a'--'c' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'd'--'g' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'h'--'k' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'l'--'o' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'p'--'s' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 't'--'w' + ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassOther, // 'x'--'z', '{' + ClassOther, ClassOther, ClassOther, ClassInvalid // '|', '}', '~', control 7F +}; + + + +int csxml_feedChar(struct csxml* ctx, char ch) +{ + enum TokenClass c; + int try; + +#ifdef DEBUG_STATE_MACHINE + printf("Character '%c' (%02X), state %d\n", ch, ch, ctx->state); +#endif + +#define ERROR(_reason) do { \ + ctx->state = StateError; \ + ctx->notWellFormed(ctx, _reason); \ + return -1; \ +}while(0) + +#define APPEND_CH(_whichbuf, _ch) do { \ + ctx-> _whichbuf .data[ctx-> _whichbuf .len++] = _ch; \ + if((ctx-> _whichbuf .len == ctx-> _whichbuf .size) && \ + do_realloc(ctx, &ctx-> _whichbuf)) return -1; \ + ctx-> _whichbuf .data[ctx-> _whichbuf .len] = 0; \ +}while(0) + +#define CLEAR_BUFFER(_whichbuf) do { \ + ctx-> _whichbuf .data[0] = 0; \ + ctx-> _whichbuf .len = 0; \ +}while(0) + +#define TRY(_x) do { \ + try = (_x); \ + if(try) { \ + ctx->state = StateError; \ + return try; \ + } \ +}while(0) + + if(ch == xmlRestartMarker[ctx->restartCount]) { + if(++ctx->restartCount == 11) { + csxml_reset(ctx); + ctx->state = StateRestartMarker; + return 0; + } + } else { + ctx->restartCount = 0; + } + + if(ch & ~0x7F) c = ClassInvalid; + else c = token_classes[(int)ch]; + + if(ch == '\r') { + ctx->skipNextNewline = 1; + ch = '\n'; + ++ctx->line; + ctx->col = 0; + } else if(ch == '\n') { + if(ctx->skipNextNewline) return 0; + ++ctx->line; + ctx->col = 0; + } else { + ctx->skipNextNewline = 0; + } + + if(c == ClassInvalid) ERROR("Restricted character encountered."); + + // deal with char appropriately, according to state + switch(ctx->state) { + case StateError: + return 0; + + case StateNone: + switch(c) { + case ClassWhitespace: + APPEND_CH(buffer, ch); + break; + + case ClassOpenTag: + if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); + ctx->state = StateOpen; + CLEAR_BUFFER(buffer); + break; + + case ClassEntity: + if(ctx->expandEntities) { + if(!ctx->elementDepth) ERROR("Entities cannot appear at stream level."); + if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); + CLEAR_BUFFER(buffer); + ctx->parsingAttr = 0; + ctx->state = StateEntity; + break; + } + + // fall through + default: + if(!ctx->elementDepth) ERROR("Content cannot appear at stream level."); + if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); + ctx->state = StateData; + CLEAR_BUFFER(buffer); + APPEND_CH(buffer, ch); + break; + } + break; + + case StateData: + switch(c) { + case ClassOpenTag: + TRY(ctx->content(ctx, ctx->buffer.data)); + CLEAR_BUFFER(buffer); + ctx->state = StateOpen; + break; + + case ClassEntity: + ctx->parsingAttr = 0; + ctx->state = StateEntity; + break; + + default: + APPEND_CH(buffer, ch); + break; + } + break; + + case StateCDATA: + if(ch == ']') ctx->state = StateCDATA1; + else APPEND_CH(buffer, ch); + break; + + case StateCDATA1: + if(ch == ']') ctx->state = StateCDATA2; + else { + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ch); + ctx->state = StateCDATA; + } + break; + + case StateCDATA2: + if(ch == '>') { + TRY(ctx->cdata(ctx, ctx->buffer.data)); + CLEAR_BUFFER(buffer); + ctx->state = StateNone; + } else if(ch == ']') { + APPEND_CH(buffer, ']'); + } else { + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ch); + ctx->state = StateCDATA; + } + break; + + case StateRestartMarker: + if(ch == ']') ctx->state = StateRestartMarker1; + else APPEND_CH(buffer, ch); + break; + + case StateRestartMarker1: + if(ch == ']') ctx->state = StateRestartMarker2; + else { + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ch); + ctx->state = StateRestartMarker; + } + break; + + case StateRestartMarker2: + if(ch == '>') { + TRY(ctx->streamRestart(ctx, ctx->buffer.data)); + csxml_reset(ctx); + + } else if(ch == ']') { + APPEND_CH(buffer, ']'); + + } else { + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ']'); + APPEND_CH(buffer, ch); + ctx->state = StateRestartMarker; + } + break; + + case StateOpen: + switch(c) { + case ClassNameStartChar: + ctx->state = StateElemName; + ctx->elemAttrNames.len = 0; + ctx->elemAttrVals.len = 0; + CLEAR_BUFFER(elemName); + APPEND_CH(elemName, ch); + break; + + default: + if(ch == '!') ctx->state = StateOpenBang; + else if(ch == '?') { + ctx->state = StatePI; + CLEAR_BUFFER(buffer2); + } else if(ch == '/') { + if(!ctx->elementDepth) ERROR("Encountered a close tag at stream level."); + ctx->state = StateClose; + } else ERROR("Invalid start character for element."); + break; + } + break; + + case StatePI: + if(ch == '?') ctx->state = StatePI2; + else if(c == ClassWhitespace) { + ctx->state = StatePIData; + CLEAR_BUFFER(buffer); + } else APPEND_CH(buffer2, ch); + break; + + case StatePI2: + if(ch != '>') ERROR("Invalid target for PI"); + else { + TRY(ctx->PI(ctx, ctx->buffer2.data, 0)); + ctx->state = StateNone; + } + break; + + case StatePIData: + if(ch == '?') ctx->state = StatePI3; + else APPEND_CH(buffer, ch); + break; + + case StatePI3: + if(ch == '>') { + TRY(ctx->PI(ctx, ctx->buffer2.data, ctx->buffer.data)); + CLEAR_BUFFER(buffer); + ctx->state = StateNone; + } else if(ch == '?') { + APPEND_CH(buffer, '?'); + } else { + APPEND_CH(buffer, '?'); + APPEND_CH(buffer, ch); + ctx->state = StatePIData; + } + break; + + case StateOpenBang: + if(ch == '[') { + // restart markers handled by lower layer + ctx->state = StateOpenCdataMarker; + ctx->xmlCount = 3; + if(!ctx->elementDepth) ERROR("CDATA sections not valid at stream level."); + } else if(ch == '-') ctx->state = StateOpenComment; + else ERROR("Invalid special tag."); + break; + + case StateOpenCdataMarker: + if(ch != xmlCdataMarker[ctx->xmlCount]) ERROR("Invalid marked section."); + if(!xmlCdataMarker[++ctx->xmlCount]) ctx->state = StateCDATA; + break; + + case StateOpenComment: + if(ch != '-') ERROR("Invalid special tag."); + ctx->state = StateComment; + CLEAR_BUFFER(buffer); + break; + + case StateComment: + if(ch == '-') ctx->state = StateComment2; + else APPEND_CH(buffer, ch); + break; + + case StateComment2: + if(ch == '-') ctx->state = StateComment3; + else { + APPEND_CH(buffer, '-'); + APPEND_CH(buffer, ch); + } + break; + + case StateComment3: + if(ch != '>') ERROR("`--' not valid in comments"); + TRY(ctx->comment(ctx, ctx->buffer.data)); + CLEAR_BUFFER(buffer); + ctx->state = StateNone; + break; + + case StateElemName: + switch(c) { + case ClassWhitespace: + ctx->state = StateElemTag; + CLEAR_BUFFER(buffer); + break; + + case ClassNameStartChar: + case ClassNameChar: + APPEND_CH(elemName, ch); + break; + + default: + switch(ch) { + case L'>': + TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); + TRY(ctx->element(ctx, ctx->elemName.data, 0)); + ctx->state = StateNone; + ++ctx->elementDepth; + CLEAR_BUFFER(buffer); + break; + + case L'/': + ctx->state = StateNeedClose; + break; + + default: + ERROR("Invalid character in tag name."); + } + } + break; + + case StateElemTag: + switch(c) { + case ClassWhitespace: + break; + + case ClassNameStartChar: + ctx->state = StateElemAttrName; + CLEAR_BUFFER(buffer); + APPEND_CH(buffer, ch); + break; + + default: + switch(ch) { + case '>': + TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); + TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len)); + ctx->state = StateNone; + ++ctx->elementDepth; + break; + + case '/': + ctx->state = StateNeedClose; + break; + + default: + ERROR("Invalid character in tag."); + } + } + break; + + case StateElemAttrName: + switch(c) { + case ClassNameStartChar: + case ClassNameChar: + APPEND_CH(buffer, ch); + break; + + default: + if(ch != '=') ERROR("Invalid character in attribute name."); + TRY(list_push(ctx, &ctx->elemAttrNames, &ctx->buffer)); + CLEAR_BUFFER(buffer); + ctx->state = StateElemAttrEq; + break; + } + break; + + case StateElemAttrEq: + if(ch == '\'') ctx->singleQuote = 1; + else if(ch == '"') ctx->singleQuote = 0; + else ERROR("Invalid character in attribute."); + ctx->state = StateElemAttrVal; + break; + + case StateElemAttrVal: + if((ctx->singleQuote && ch == '\'') || (!ctx->singleQuote && ch == '"')) { + TRY(list_push(ctx, &ctx->elemAttrVals, &ctx->buffer)); + ctx->state = StateElemAttrDone; + } else if(ctx->expandEntities && ch == L'&') { + ctx->parsingAttr = 1; + ctx->state = StateEntity; + } else APPEND_CH(buffer, ch); + break; + + case StateElemAttrDone: + switch(c) { + case ClassWhitespace: + ctx->state = StateElemTag; + break; + + default: + if(ch == '/') { + ctx->state = StateNeedClose; + } else if(ch == '>') { + TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); + TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); + CLEAR_BUFFER(buffer); + ctx->state = StateNone; + ++ctx->elementDepth; + } else ERROR("Invalid character after attribute."); + break; + } + break; + + case StateNeedClose: + if(ch != '>') ERROR("Stray `/' in open tag."); + TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); + TRY(ctx->closeTag(ctx, ctx->elemName.data)); + CLEAR_BUFFER(buffer); + ctx->state = StateNone; + break; + + case StateClose: + if(c != ClassNameStartChar) ERROR("Invalid character in close tag name."); + APPEND_CH(buffer, ch); + ctx->state = StateClosing; + break; + + case StateClosing: + switch(c) { + case ClassNameStartChar: + case ClassNameChar: + APPEND_CH(buffer, ch); + break; + + case ClassWhitespace: + ctx->state = StateNeedClose2; + break; + + default: + if(ch != '>') ERROR("Invalid character in close tag name."); + TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); + if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); + TRY(ctx->closeTag(ctx, ctx->elemName.data)); + ctx->state = StateNone; + --ctx->elementDepth; + CLEAR_BUFFER(buffer); + + } + break; + + case StateNeedClose2: + if(c == ClassWhitespace) break; + if(ch != '>') ERROR("Invalid data in close tag."); + TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); + if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); + TRY(ctx->closeTag(ctx, ctx->elemName.data)); + ctx->state = StateNone; + --ctx->elementDepth; + CLEAR_BUFFER(buffer); + break; + + case StateEntity: + if(ch == '#') { + ctx->state = StateCharEntity; + ctx->entityChar = 0; + } else if(c == ClassNameStartChar) { + APPEND_CH(buffer, ch); + ctx->state = StateEntityName; + } else ERROR("Invalid entity name."); + break; + + case StateCharEntity: + if(ch == ';') { + APPEND_CH(buffer, ctx->entityChar); + ctx->state = ctx->parsingAttr ? StateElemAttrVal : StateData; + break; + + } else if(ch >= '0' && ch <= '9') { + ctx->entityChar *= 10; + ctx->entityChar += (ch - '0'); + if(!ctx->entityChar || ctx->entityChar > 126) ERROR("Character code out of range in character entity."); + } else ERROR("Invalid character in character entity."); + break; + + case StateEntityName: + if(ch == ';') { + const char* e = csxml_entityRef(ctx, ctx->buffer2.data); + TRY(!e || buffer_strcat(ctx, &ctx->buffer, e)); + ctx->state = ctx->parsingAttr ? StateElemAttrVal : StateData; + break; + } + if(c != ClassNameChar && c != ClassNameStartChar) ERROR("Invalid entity name."); + APPEND_CH(buffer2, ch); + break; + } + ++ctx->col; + return 0; +} + + + +const char* csxml_entityRef(struct csxml* ctx, const char* ent) +{ + const char* q = 0; + + if(!strcmp(ent, "quot")) return "\""; + if(!strcmp(ent, "amp")) return "&"; + if(!strcmp(ent, "apos")) return "'"; + if(!strcmp(ent, "lt")) return "<"; + if(!strcmp(ent, "gt")) return ">"; + + q = ctx->entityRef(ctx, ent); + if(!q) { + ctx->unknownEntity(ctx, ent); + ctx->state = StateError; + return 0; + } + + return q; +} + + + +void csxml_reset(struct csxml* ctx) +{ + CLEAR_BUFFER(buffer); + CLEAR_BUFFER(buffer2); + CLEAR_BUFFER(elemName); + ctx->state = StateNone; + ctx->xmlCount = 0; + ctx->elementDepth = 0; + ctx->restartCount = 0; + ctx->skipNextNewline = 0; + ctx->parsingAttr = 0; + ctx->line = 0; + ctx->col = 0; + ctx->elemStack.len = 0; + ctx->elemAttrNames.len = 0; + ctx->elemAttrVals.len = 0; +} + + + +#undef ERROR +#undef APPEND_CH +#undef CLEAR_BUFFER + + + +void csxml_freeParser(struct csxml* ctx) +{ + if(!ctx) return; + buffer_free(&ctx->buffer); + buffer_free(&ctx->buffer2); + buffer_free(&ctx->elemName); + list_free(&ctx->elemStack); + list_free(&ctx->elemAttrNames); + list_free(&ctx->elemAttrVals); +} + + + +struct csxml* csxml_newParser() +{ + struct csxml* ctx = 0; + + ctx = malloc(sizeof(struct csxml)); + if(!ctx) return 0; + memset(ctx, 0, sizeof(struct csxml)); + + if(buffer_init(ctx, &ctx->buffer) || buffer_init(ctx, &ctx->buffer2) || buffer_init(ctx, &ctx->elemName)) { + csxml_freeParser(ctx); + return 0; + } + + ctx->expandEntities = 1; + + ctx->notWellFormed = default_notWellFormed; + ctx->outOfMemory = default_outOfMemory; + ctx->unknownEntity = default_unknownEntity; + ctx->whiteSpace = default_discard; + ctx->content = default_discard; + ctx->cdata = default_cdata; + ctx->streamRestart = default_discard; + ctx->PI = default_discardPI; + ctx->comment = default_discard; + ctx->element = default_discardElem; + ctx->closeTag = default_discard; + ctx->entityRef = default_discardEnt; + + return ctx; +} + + + +void csxml_feedData(struct csxml* ctx, const char* data, size_t amt) +{ + while(amt--) csxml_feedChar(ctx, *data++); +} + + + +/* 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/libCStreamedXML/pkgconf.in b/src/libCStreamedXML/pkgconf.in new file mode 100644 index 0000000..ba36045 --- /dev/null +++ b/src/libCStreamedXML/pkgconf.in @@ -0,0 +1,21 @@ +# libCStreamedXML/src/lib/clib/pkgconf.in +# +# Metadata file for pkg-config +# ( http://www.freedesktop.org/software/pkgconfig/ ) +# +# (c)2006, Laurence Withers, . +# Released under the GNU GPLv2. See file COPYING or +# http://www.gnu.org/copyleft/gpl.html for details. +# + +# Name, description +Name: @TODO@ +Description: @TODO@ +Version: @VERSION@ + +# Requirements +Requires: + +# Compilation information +Libs: -L@LIBDIR@ -lCStreamedXML +Cflags: -I@INCLUDEDIR@ diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion new file mode 100644 index 0000000..af384de --- /dev/null +++ b/src/libCStreamedXML/soversion @@ -0,0 +1,17 @@ +# libCStreamedXML/src/libCStreamedXML/soversion +# +# (c)2006, Laurence Withers, . +# Released under the GNU GPLv2. See file COPYING or +# http://www.gnu.org/copyleft/gpl.html for details. +# + + + +# SOMAJOR and SOMINOR are included in the library's soname. They need to +# be bumped on a binary-incompatible release. They are both single +# integers. +SOMAJOR=0 +SOMINOR=0 + +# SOMICRO is bumped every time there is a binary-compatible release. +SOMICRO=0 diff --git a/src/libCStreamedXML/types.h b/src/libCStreamedXML/types.h new file mode 100644 index 0000000..95442b6 --- /dev/null +++ b/src/libCStreamedXML/types.h @@ -0,0 +1,320 @@ +/* libCStreamedXML/src/libCStreamedXML/types.h + * + * (c)2006, Laurence Withers. Released under the GNU GPL. See file + * COPYING for more information / terms of license. +*/ + + + +/*! \brief String buffer. + +This type implements a simple string buffer. The string should be kept null-terminated. The \a data +pointer is reallocated as necessary (i.e. when \a len becomes equal to \a size). \a len is the +string length (excluding terminating null) and \a size is the size of the allocated buffer. It is +never valid for \a data or \a size to be 0. + +*/ +struct csxml_buf { + /// Pointer to string (null terminated). + char* data; + + /// Length of string (excluding null). + size_t len; + + /// Size of allocated buffer. + size_t size; +}; + + + +/*! \brief String list. + +This type implements a dynamic array of strings (using the struct csxml_buf type). The \a data +pointer is reallocated as necessary (i.e. when \a len becomes equal to \a size). \a len is the +number of valid elements in the array and \a size is the size of the allocated buffer. It is valid +for \a data and \a size to be zero. + +*/ +struct csxml_list { + /// Array of buffers (all allocated elements are valid and initialised). + struct csxml_buf* data; + + /// Number of elements in use. + size_t len; + + /// Number of allocated elements. + size_t size; +}; + + + +/*! \brief Streamed XML parser context. + +This structure contains all the details of a Streamed XML parsing operation. Most fields are +internal to the parser and should not be touched; those are briefly documented here. You may want to +change the \a expandEntities option, examine the \a line and \a col variables, and change the +callback functions. + +Those members marked Internal: are subject to change (either in semantics, type or existence). + +*/ +struct csxml { + /// Option: change "&lt;" to "<", etc. if non-zero (the default). Change to 0 to leave + /// entities inline. + int expandEntities; + + /// Current line (from 0, starts from last restart marker). + int line; + /// Current column (from 0, starts from last restart marker). + int col; + + /// List of attribute names for current element. + struct csxml_list elemAttrNames; + /// List of attribute values for current element. + struct csxml_list elemAttrVals; + + + + /*! \brief Error callback: Streamed XML is not well formed. + + \param ctx Parsing context. + \param reason Human-readable description of error. + + This function is called whenever badly-formed Streamed XML is encountered (e.g. if content is + encountered at stream-level). + + The default implementation prints a formatted message to \a stderr. + + */ + void (*notWellFormed)(const struct csxml* ctx, const char* reason); + + + + /*! \brief Error callback: out of memory. + + \param ctx Parsing context. + \param amount Number of bytes we tried to allocate. + + This function is called whenever a dynamic string resizing operation (or similar) fails. It is + called with the number of bytes the library attempted to allocate. + + The default implementation prints a formatted message to \a stderr. + + \todo When parsing extremely long content sections, we could just call the content() callback + when memory is low rather than failing altogether. + + */ + void (*outOfMemory)(const struct csxml* ctx, size_t amount); + + + + /*! \brief Error callback: reference to unknown entity. + + \param ctx Parsing context. + \param ent Name of the referenced entity. + + If an entity is referenced by name (e.g. "&myEntity;" is encountered) but the lookup in the + default entity list and through the entityRef() callback fails to resolve the content, this + function is called. + + The default implementation prints a formatted message to \a stderr. + + */ + void (*unknownEntity)(const struct csxml* ctx, const char* ent); + + + + /*! \brief Callback: whitespace. + + \param ctx Parsing context. + \param ws Pointer to string of whitespace. + \returns Zero on success, non-zero on error. + + This function is called whenever a block of whitespace is encountered at stream level or + immediately after some structural element (i.e. on leading whitespace within elements). It is + generally safe to discard it, unless you need to reproduce the file verbatim. Once content is + encountered within an element, any further whitespace will be reported through the content() + callback, up to the next structural element. + + The default implementation discards the data. + + */ + int (*whiteSpace)(const struct csxml* ctx, const char* ws); + + + + /*! \brief Callback: content. + + \param ctx Parsing context. + \param content Pointer to string of cdata. + \returns Zero on success, non-zero on error. + + This function is called whenever textual content (cdata) is encountered inside an element. It + may be called multiple times simultaneously, in which case the data from each call should be + concatenated. If \a expandEntities is non-zero, then this function will also be called with the + expanded text from any entities encountered, rather than the entities themselves. + + The default implementation discards the data. + + */ + int (*content)(const struct csxml* ctx, const char* content); + + + + /*! \brief Callback: cdata block. + + \param ctx Parsing context. + \param cdata Pointer to string of cdata. + \returns Zero on success, non-zero on error. + + This function is called for all data inside a CDATA marked section. It is useful to + differentiate between cdata encoded in this manner and normal cdata if you are trying to + reproduce the orginal file verbatim. + + The default implementation calls content() with the same data. + + */ + int (*cdata)(const struct csxml* ctx, const char* cdata); + + + + /*! \brief Callback: stream restart marker. + + \param ctx Parsing context. + \param marker Pointer to marker string. + \returns Zero on success, non-zero on error. + + Whenever a stream restart marker is encountered, this function is called with the data found + inside the marker. + + The default implementation ignores the data (but note that the parser state is always reset, + regardless of what the callback does). + + */ + int (*streamRestart)(const struct csxml* ctx, const char* marker); + + + + /*! \brief Callback: processing instruction. + + \param ctx Parsing context. + \param target PI target. + \param data PI data (may be 0). + \returns Zero on success, non-zero on error. + + This callback is used to report processing instructions (PIs). If the PI has no data, then the + \a data variable can be set to 0. + + The default implementation ignores the data. + + */ + int (*PI)(const struct csxml* ctx, const char* target, const char* data); + + + + /*! \brief Callback: comment. + + \param ctx Parsing context. + \param comment Pointer to comment string data. + \returns Zero on success, non-zero on error. + + This callback is used to report comments. It is only useful if you wish to reproduce the source + file verbatim (for instance, you want to alter some data in a file but preserve user comments). + + The default implementation ignores the data. + + */ + int (*comment)(const struct csxml* ctx, const char* comment); + + + + /*! \brief Callback: element. + + \param ctx Parsing context. + \param elemName Pointer to element name string. + \param numAttrs Number of attributes. + \returns Zero on success, non-zero on error. + + This callback is used whenever an element open tag is encountered. To parse attributes, use the + numAttrs variable to determine how many there are, and then access them with: + +
        // get attribute name
+        const char* elemName = ctx->elemAttrNames.data[i].data;
+
+        // get attribute value
+        const char* elemValue = ctx->elemAttrValues.data[i].data;
+ + In the case of an empty element, the closeTag() callback will be called immediately afterwards. + + The default implemenation ignores the data. + + */ + int (*element)(const struct csxml* ctx, const char* elemName, int numAttrs); + + + + /*! \brief Callback: close tag. + + \param ctx Parsing context. + \param elemName Element name. + \returns Zero on success, non-zero on error. + + This function is called whenever an element close tag is encountered. The element name will + always match the open tag element name (if not, the Streamed XML is not well formed, and an + error will be signalled before this callback is triggered). + + The default implementation ignores the data. + + */ + int (*closeTag)(const struct csxml* ctx, const char* elemName); + + + + /*! \brief Callback: entity reference. + + \param ctx Parsing context. + \param ent Entity name. + \retval 0 if the entity name does not match any known entity. + \returns Pointer to null-terminated string data for expanding entity. + + This function is called whenever \a expandEntities is true and an entity is encountered in cdata + or an attribute value. It is only called if the entity does not match one of the five built-in + defaults. You only need to provide an implementation if you know about some additional entities. + + The default implementation returns 0 ("no such entity"). + + */ + const char* (*entityRef)(const struct csxml* ctx, const char* ent); + + + + /// Internal: string buffer. + struct csxml_buf buffer; + /// Internal: string buffer. + struct csxml_buf buffer2; + /// Internal: string buffer. + struct csxml_buf elemName; + /// Internal: stack of element names, used to match open/close tags. + struct csxml_list elemStack; + /// Internal: state machine state. + int state; + /// Internal: for matching strings. + int xmlCount; + /// Internal: depth in element tree (0 = stream level). + int elementDepth; + /// Internal: for matching against restart marker string. + int restartCount; + /// Internal: for stripping windows line endings. + int skipNextNewline; + /// Internal: flag to check if we are currently parsing an attribute while expanding an entity. + int parsingAttr; + /// Internal: flag to record if current attribute was quoted with ' or " char. + int singleQuote; + /// Internal: used to expand character entities. + int entityChar; +}; + +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/ From a2ca4f8122bceb338d027bc388bc55e52b47aebb Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Tue, 8 Aug 2006 14:51:50 +0100 Subject: [PATCH 05/18] Add user pointer, bump version. --- src/libCStreamedXML/.functions.h.swp | Bin 12288 -> 0 bytes src/libCStreamedXML/types.h | 2 ++ version | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 src/libCStreamedXML/.functions.h.swp diff --git a/src/libCStreamedXML/.functions.h.swp b/src/libCStreamedXML/.functions.h.swp deleted file mode 100644 index 9dd2f80f06035a47e75c0167891908de2cfdae6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHN&yO6%6)u8FNX(BYa7r!@!ePCcnOzf$M7EGf3^A6By%?K>#FAChT|HfFcU7yZ zdS}NFatJ3Rat`FDatT-hkv{>2D1k`%p@b5c>cnkO~kO7B)Ki`gbfja_7N5uPIVe`I(9;Atdp(cRUOK# zqo8&JsZJ1mwsN9!Hc{TwS|W>L zER*d4Dd#{1W(9SGch785*r`efG_Kine$-xYYK)&-ylT~mF62sF*#82%u1HDn!L-RF zD95faEo0ou+9sPtM@DoyBWYTbu(2|UtqrELIXu1gwJacwSW=eEIGwG_F_yy$<5^H3 z&qk`%Xg(q=uaXt&7r7gD8Mb?oRBXpegd+5^GX_Yl&;B)0|u9&5~0oy9< zPntF@mb_uE;2*v@5QwbI*gT{gZknwGjYHy47P71gxOD)*aofmGq?*ZvqdH&%ql1=3 z6W#$yPA*$dax%6_om{3gQ-Q`x8S03=5gX^(&xU6Qp3no9ilQkYRG<#C^D5g<$KD#k z#Fn4hY#Tc@kHj}4F`S`Dh!l*3+8IxqBVmy^HagpFv6zcAm=_!9)EOC+jY?x;@j&wm z^KNVaueCv9X_Pafz}&3n?;=3hGesU|02gmuNGp$(xz5y2UTPs zAATVJwSm@Lnme?Vn5Hg@A+n&<2DO-SGO%F4rA89*s5PH;3;B&Tb`aZ5$VpQ&UCv`3 zJ<`x|Z!W)O$N2i8Sb8^b;`RgwBijtj*Ulrkha4;@@0V3$=36T~?V57ed8ktl7AeC!o6 zuTfDmO0`coU{NS4={<;!M;Pb~#VQFmgtGSFyxQ#l`6j>^91^`NUQEY#g%(vgje%IS*2M6`m!@bq;n&#QO*AWR7PIdC&NFN}F%tDW zXL(U8h!u*3sf#gO48$Vxb;8|oQ7$=gwl@t6DG|L|jQ*D`W8ph1 z8GQ>=n8sGu+caU)k?&j=Eb>TMn=oT-4mXFE8Wl&pFd~2~Ewm5#P$3!NsIlDkE-dmC zKC)4?R>~O{?IurM>Vj-eWOWy-aW(F-D~d(4d3R!p$0?(xt)ENk5XtGgJTnncfzt!xgmWsb6P-M__0;LJr{WQ#w2qaNg+%fpnKp1j zcBSV$D|7<-(MkBFwdBbCo0|^|=!`^`vEF{Wxq?5U^Qusi6%?Hn^20$qb@n2i+B!3$ aCt!J|3xzfKB))o${-CS%VOF8X=Hfq!?3wWZ diff --git a/src/libCStreamedXML/types.h b/src/libCStreamedXML/types.h index 95442b6..90cc865 100644 --- a/src/libCStreamedXML/types.h +++ b/src/libCStreamedXML/types.h @@ -73,6 +73,8 @@ struct csxml { /// List of attribute values for current element. struct csxml_list elemAttrVals; + /// User data. + void* user; /*! \brief Error callback: Streamed XML is not well formed. diff --git a/version b/version index b0f29f4..fd37c10 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=0 +VERMICRO=1 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From 0cc4d09d658c9f5598ce440fef90e5d5e40c7234 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 25 Aug 2006 10:42:32 +0100 Subject: [PATCH 06/18] Upgrade to new build system. --- make.sh | 6 +++++- scripts/.gitignore | 1 + src/libCStreamedXML/BottomHeader.h | 2 +- src/libCStreamedXML/build.lib | 2 +- src/libCStreamedXML/build.monolithic | 2 +- src/libCStreamedXML/pkgconf.in | 2 +- src/libCStreamedXML/soversion | 4 ++-- src/libStreamedXML/build.lib | 2 +- src/libStreamedXML/build.monolithic | 2 +- src/libStreamedXML/soversion | 2 +- version | 2 +- 11 files changed, 16 insertions(+), 11 deletions(-) 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/libCStreamedXML/BottomHeader.h b/src/libCStreamedXML/BottomHeader.h index 072d08e..3034856 100644 --- a/src/libCStreamedXML/BottomHeader.h +++ b/src/libCStreamedXML/BottomHeader.h @@ -1,4 +1,4 @@ -/* libCStreamedXML/src/clib/BottomHeader.h +/* libCStreamedXML/src/libCStreamedXML/BottomHeader.h * * (c)2006, Laurence Withers, . * Released under the GNU GPLv2. See file COPYING or diff --git a/src/libCStreamedXML/build.lib b/src/libCStreamedXML/build.lib index 5d316e8..2b86961 100644 --- a/src/libCStreamedXML/build.lib +++ b/src/libCStreamedXML/build.lib @@ -31,7 +31,7 @@ then echo " Compiling" SONAME="${libCStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}" - do_cmd ${CC} ${CFLAGS} -shared -fpic -o "${libCStreamedXML}" \ + do_cmd ${CC} ${CFLAGS} -Iobj -shared -fpic -o "${libCStreamedXML}" \ -Wl,-soname,${SONAME} \ ${SRC} ${SO_EXTRA} || return 1 diff --git a/src/libCStreamedXML/build.monolithic b/src/libCStreamedXML/build.monolithic index a6027c4..733082a 100644 --- a/src/libCStreamedXML/build.monolithic +++ b/src/libCStreamedXML/build.monolithic @@ -9,7 +9,7 @@ MONOLITHIC_TESTS="src/libCStreamedXML/build.lib src/libCStreamedXML/build.monoli if [ -z "${libCStreamedXML_MONOLITHIC}" ] then MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopHeader,types,functions,BottomHeader}.h)" - make_monolithic ${HDR} C || return 1 + make_monolithic ${HDR} Ch || return 1 MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopSource,buffer,defaults,parser}.c)" make_monolithic ${SRC} C || return 1 diff --git a/src/libCStreamedXML/pkgconf.in b/src/libCStreamedXML/pkgconf.in index ba36045..540604f 100644 --- a/src/libCStreamedXML/pkgconf.in +++ b/src/libCStreamedXML/pkgconf.in @@ -1,4 +1,4 @@ -# libCStreamedXML/src/lib/clib/pkgconf.in +# libStreamedXML/src/lib/libCStreamedXML/pkgconf.in # # Metadata file for pkg-config # ( http://www.freedesktop.org/software/pkgconfig/ ) diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion index af384de..3a95b4b 100644 --- a/src/libCStreamedXML/soversion +++ b/src/libCStreamedXML/soversion @@ -1,4 +1,4 @@ -# libCStreamedXML/src/libCStreamedXML/soversion +# libStreamedXML/src/libCStreamedXML/soversion # # (c)2006, Laurence Withers, . # Released under the GNU GPLv2. See file COPYING or @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=0 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=0 +SOMICRO=1 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 f0f1c97..8db4e6b 100644 --- a/src/libStreamedXML/soversion +++ b/src/libStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=1 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=0 +SOMICRO=1 diff --git a/version b/version index fd37c10..27bfeca 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=1 +VERMICRO=2 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From c2d02165d754c6aecda5fca2aea9dace2e33c781 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 25 Aug 2006 10:43:56 +0100 Subject: [PATCH 07/18] Edit pkgconf file, bump version. --- src/libCStreamedXML/pkgconf.in | 4 ++-- version | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libCStreamedXML/pkgconf.in b/src/libCStreamedXML/pkgconf.in index 540604f..acdb6c5 100644 --- a/src/libCStreamedXML/pkgconf.in +++ b/src/libCStreamedXML/pkgconf.in @@ -9,8 +9,8 @@ # # Name, description -Name: @TODO@ -Description: @TODO@ +Name: libCStreamedXML +Description: C library for parsing Streamed XML Version: @VERSION@ # Requirements diff --git a/version b/version index 27bfeca..4778acb 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=2 +VERMICRO=3 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From 8e3798dbbcae001ea7a424369b90e16f7e34c0c0 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 8 Sep 2006 14:04:46 +0100 Subject: [PATCH 08/18] Add cast for printf() --- src/libCStreamedXML/defaults.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCStreamedXML/defaults.c b/src/libCStreamedXML/defaults.c index b4d147e..a02e2f1 100644 --- a/src/libCStreamedXML/defaults.c +++ b/src/libCStreamedXML/defaults.c @@ -15,7 +15,7 @@ static void default_notWellFormed(const struct csxml* ctx, const char* reason) static void default_outOfMemory(const struct csxml* ctx, size_t amount) { (void)ctx; - fprintf(stderr, "Streamed XML parser: out of memory allocating %lu bytes\n", amount); + fprintf(stderr, "Streamed XML parser: out of memory allocating %lu bytes\n", (unsigned long)amount); } From f1fa8b5625ceafa6fad2d970f3bf2f8ff719d5cf Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 29 Sep 2006 10:41:01 +0100 Subject: [PATCH 09/18] Fix a bug where two separate '-' characters in a comment were interpreted as a single '--' sequence. --- src/libCStreamedXML/parser.c | 1 + src/libStreamedXML/Parser.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c index cf1fcfb..752c714 100644 --- a/src/libCStreamedXML/parser.c +++ b/src/libCStreamedXML/parser.c @@ -372,6 +372,7 @@ int csxml_feedChar(struct csxml* ctx, char ch) else { APPEND_CH(buffer, '-'); APPEND_CH(buffer, ch); + ctx->state = StateComment; } break; diff --git a/src/libStreamedXML/Parser.cpp b/src/libStreamedXML/Parser.cpp index 5047ceb..b043282 100644 --- a/src/libStreamedXML/Parser.cpp +++ b/src/libStreamedXML/Parser.cpp @@ -354,6 +354,7 @@ doBuffer: else { buffer += L'-'; buffer += ch; + state = StateComment; } break; From 71fda149812a8dc8caaf2c20126641a8f79a8f40 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 29 Sep 2006 10:51:10 +0100 Subject: [PATCH 10/18] Update internal state before callback; that way, if during the callback we inject some more data into the parser (e.g. it's an tag or something), the parser is in the correct state. --- src/libCStreamedXML/parser.c | 30 +++++++++++++++--------------- src/libStreamedXML/Parser.cpp | 30 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c index 752c714..d0332eb 100644 --- a/src/libCStreamedXML/parser.c +++ b/src/libCStreamedXML/parser.c @@ -141,8 +141,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) if(ch == xmlRestartMarker[ctx->restartCount]) { if(++ctx->restartCount == 11) { - csxml_reset(ctx); ctx->state = StateRestartMarker; + csxml_reset(ctx); return 0; } } else { @@ -179,8 +179,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) break; case ClassOpenTag: - if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); ctx->state = StateOpen; + if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); CLEAR_BUFFER(buffer); break; @@ -197,8 +197,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) // fall through default: if(!ctx->elementDepth) ERROR("Content cannot appear at stream level."); - if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); ctx->state = StateData; + if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); CLEAR_BUFFER(buffer); APPEND_CH(buffer, ch); break; @@ -208,9 +208,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StateData: switch(c) { case ClassOpenTag: + ctx->state = StateOpen; TRY(ctx->content(ctx, ctx->buffer.data)); CLEAR_BUFFER(buffer); - ctx->state = StateOpen; break; case ClassEntity: @@ -240,9 +240,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StateCDATA2: if(ch == '>') { + ctx->state = StateNone; TRY(ctx->cdata(ctx, ctx->buffer.data)); CLEAR_BUFFER(buffer); - ctx->state = StateNone; } else if(ch == ']') { APPEND_CH(buffer, ']'); } else { @@ -317,8 +317,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StatePI2: if(ch != '>') ERROR("Invalid target for PI"); else { - TRY(ctx->PI(ctx, ctx->buffer2.data, 0)); ctx->state = StateNone; + TRY(ctx->PI(ctx, ctx->buffer2.data, 0)); } break; @@ -329,9 +329,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StatePI3: if(ch == '>') { + ctx->state = StateNone; TRY(ctx->PI(ctx, ctx->buffer2.data, ctx->buffer.data)); CLEAR_BUFFER(buffer); - ctx->state = StateNone; } else if(ch == '?') { APPEND_CH(buffer, '?'); } else { @@ -378,9 +378,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StateComment3: if(ch != '>') ERROR("`--' not valid in comments"); + ctx->state = StateNone; TRY(ctx->comment(ctx, ctx->buffer.data)); CLEAR_BUFFER(buffer); - ctx->state = StateNone; break; case StateElemName: @@ -399,8 +399,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) switch(ch) { case L'>': TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - TRY(ctx->element(ctx, ctx->elemName.data, 0)); ctx->state = StateNone; + TRY(ctx->element(ctx, ctx->elemName.data, 0)); ++ctx->elementDepth; CLEAR_BUFFER(buffer); break; @@ -430,8 +430,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) switch(ch) { case '>': TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len)); ctx->state = StateNone; + TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len)); ++ctx->elementDepth; break; @@ -488,10 +488,10 @@ int csxml_feedChar(struct csxml* ctx, char ch) if(ch == '/') { ctx->state = StateNeedClose; } else if(ch == '>') { + ctx->state = StateNone; TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); CLEAR_BUFFER(buffer); - ctx->state = StateNone; ++ctx->elementDepth; } else ERROR("Invalid character after attribute."); break; @@ -500,10 +500,10 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StateNeedClose: if(ch != '>') ERROR("Stray `/' in open tag."); + ctx->state = StateNone; TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); TRY(ctx->closeTag(ctx, ctx->elemName.data)); CLEAR_BUFFER(buffer); - ctx->state = StateNone; break; case StateClose: @@ -527,8 +527,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) if(ch != '>') ERROR("Invalid character in close tag name."); TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); - TRY(ctx->closeTag(ctx, ctx->elemName.data)); ctx->state = StateNone; + TRY(ctx->closeTag(ctx, ctx->elemName.data)); --ctx->elementDepth; CLEAR_BUFFER(buffer); @@ -540,8 +540,8 @@ int csxml_feedChar(struct csxml* ctx, char ch) if(ch != '>') ERROR("Invalid data in close tag."); TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); - TRY(ctx->closeTag(ctx, ctx->elemName.data)); ctx->state = StateNone; + TRY(ctx->closeTag(ctx, ctx->elemName.data)); --ctx->elementDepth; CLEAR_BUFFER(buffer); break; @@ -598,8 +598,8 @@ const char* csxml_entityRef(struct csxml* ctx, const char* ent) q = ctx->entityRef(ctx, ent); if(!q) { - ctx->unknownEntity(ctx, ent); ctx->state = StateError; + ctx->unknownEntity(ctx, ent); return 0; } diff --git a/src/libStreamedXML/Parser.cpp b/src/libStreamedXML/Parser.cpp index b043282..3dcc9a9 100644 --- a/src/libStreamedXML/Parser.cpp +++ b/src/libStreamedXML/Parser.cpp @@ -163,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; } @@ -191,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: @@ -225,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 { @@ -298,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; @@ -311,9 +311,9 @@ doBuffer: case StatePI3: if(ch == L'>') { + state = StateNone; callback->PI(buffer2, buffer); buffer.clear(); - state = StateNone; } else if(ch == '?') { buffer += L'?'; } else { @@ -360,9 +360,9 @@ doBuffer: case StateComment3: if(ch != L'>') ERROR(L"`--' not valid in comments"); + state = StateNone; callback->comment(buffer); buffer.clear(); - state = StateNone; break; case StateElemName: @@ -382,8 +382,8 @@ doBuffer: switch(ch) { case L'>': elemStack.push_back(buffer); - callback->element(buffer, elemAttrs); state = StateNone; + callback->element(buffer, elemAttrs); ++elementDepth; buffer.clear(); break; @@ -412,9 +412,9 @@ doBuffer: switch(ch) { case L'>': elemStack.push_back(elemName); + state = StateNone; callback->element(elemName, elemAttrs); buffer.clear(); - state = StateNone; ++elementDepth; break; @@ -474,10 +474,10 @@ doBuffer: if(ch == L'/') { state = StateNeedClose; } else if(ch == L'>') { + state = StateNone; callback->element(elemName, elemAttrs); elemStack.push_back(elemName); buffer.clear(); - state = StateNone; ++elementDepth; } else ERROR(L"Invalid character after attribute."); break; @@ -486,10 +486,10 @@ doBuffer: case StateNeedClose: if(ch != L'>') ERROR(L"Stray `/' in open tag."); + state = StateNone; callback->element(elemName, elemAttrs); callback->closeTag(elemName); buffer.clear(); - state = StateNone; break; case StateClose: @@ -513,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(); + state = StateNone; callback->closeTag(buffer); buffer.clear(); - state = StateNone; --elementDepth; } break; @@ -525,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(); + state = StateNone; callback->closeTag(elemName); buffer.clear(); - state = StateNone; --elementDepth; break; From a24d2caad2b1a42463b592f6c076e57e759b7770 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 29 Sep 2006 10:56:50 +0100 Subject: [PATCH 11/18] Bump version. --- src/libCStreamedXML/soversion | 2 +- src/libStreamedXML/soversion | 2 +- version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion index 3a95b4b..09c7a32 100644 --- a/src/libCStreamedXML/soversion +++ b/src/libCStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=0 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=1 +SOMICRO=2 diff --git a/src/libStreamedXML/soversion b/src/libStreamedXML/soversion index 8db4e6b..a12fb52 100644 --- a/src/libStreamedXML/soversion +++ b/src/libStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=1 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=1 +SOMICRO=2 diff --git a/version b/version index 4778acb..e495b19 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=3 +VERMICRO=4 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From 9a33766c6217f3beb247bead75b41258b97e78a0 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Wed, 4 Oct 2006 10:47:19 +0100 Subject: [PATCH 12/18] Further to the previous fix, don't clear the content buffer afetr an open/close tag callback -- clear it before. This stops included content from being lost. --- src/libCStreamedXML/parser.c | 13 ++++++------- src/libStreamedXML/Parser.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c index d0332eb..cffb56a 100644 --- a/src/libCStreamedXML/parser.c +++ b/src/libCStreamedXML/parser.c @@ -110,7 +110,7 @@ int csxml_feedChar(struct csxml* ctx, char ch) int try; #ifdef DEBUG_STATE_MACHINE - printf("Character '%c' (%02X), state %d\n", ch, ch, ctx->state); + printf("%p: Character '%c' (%02X), state %d, buffer %s\n", ctx, ch, ch, ctx->state, ctx->buffer.data); #endif #define ERROR(_reason) do { \ @@ -398,11 +398,11 @@ int csxml_feedChar(struct csxml* ctx, char ch) default: switch(ch) { case L'>': + CLEAR_BUFFER(buffer); TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); ctx->state = StateNone; TRY(ctx->element(ctx, ctx->elemName.data, 0)); ++ctx->elementDepth; - CLEAR_BUFFER(buffer); break; case L'/': @@ -489,9 +489,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) ctx->state = StateNeedClose; } else if(ch == '>') { ctx->state = StateNone; + CLEAR_BUFFER(buffer); TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - CLEAR_BUFFER(buffer); ++ctx->elementDepth; } else ERROR("Invalid character after attribute."); break; @@ -501,9 +501,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) case StateNeedClose: if(ch != '>') ERROR("Stray `/' in open tag."); ctx->state = StateNone; + CLEAR_BUFFER(buffer); TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); TRY(ctx->closeTag(ctx, ctx->elemName.data)); - CLEAR_BUFFER(buffer); break; case StateClose: @@ -528,10 +528,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); ctx->state = StateNone; + CLEAR_BUFFER(buffer); TRY(ctx->closeTag(ctx, ctx->elemName.data)); --ctx->elementDepth; - CLEAR_BUFFER(buffer); - } break; @@ -541,9 +540,9 @@ int csxml_feedChar(struct csxml* ctx, char ch) TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); ctx->state = StateNone; + CLEAR_BUFFER(buffer); TRY(ctx->closeTag(ctx, ctx->elemName.data)); --ctx->elementDepth; - CLEAR_BUFFER(buffer); break; case StateEntity: diff --git a/src/libStreamedXML/Parser.cpp b/src/libStreamedXML/Parser.cpp index 3dcc9a9..ee6f0f6 100644 --- a/src/libStreamedXML/Parser.cpp +++ b/src/libStreamedXML/Parser.cpp @@ -383,9 +383,9 @@ doBuffer: case L'>': elemStack.push_back(buffer); state = StateNone; + buffer.clear(); callback->element(buffer, elemAttrs); ++elementDepth; - buffer.clear(); break; case L'/': @@ -413,8 +413,8 @@ doBuffer: case L'>': elemStack.push_back(elemName); state = StateNone; - callback->element(elemName, elemAttrs); buffer.clear(); + callback->element(elemName, elemAttrs); ++elementDepth; break; @@ -475,9 +475,9 @@ doBuffer: state = StateNeedClose; } else if(ch == L'>') { state = StateNone; + buffer.clear(); callback->element(elemName, elemAttrs); elemStack.push_back(elemName); - buffer.clear(); ++elementDepth; } else ERROR(L"Invalid character after attribute."); break; @@ -487,9 +487,9 @@ 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(); break; case StateClose: @@ -514,8 +514,8 @@ doBuffer: if(elemStack.back() != buffer) ERROR(L"Mismatched close tag."); elemStack.pop_back(); state = StateNone; - callback->closeTag(buffer); buffer.clear(); + callback->closeTag(buffer); --elementDepth; } break; @@ -526,8 +526,8 @@ doBuffer: if(elemStack.back() != elemName) ERROR(L"Mismatched close tag."); elemStack.pop_back(); state = StateNone; - callback->closeTag(elemName); buffer.clear(); + callback->closeTag(elemName); --elementDepth; break; From d46aaf2b2e16e3a81478fd3bb3ea1723caf33596 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Wed, 4 Oct 2006 10:47:52 +0100 Subject: [PATCH 13/18] Doc fix. --- src/libCStreamedXML/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCStreamedXML/types.h b/src/libCStreamedXML/types.h index 90cc865..16a6ced 100644 --- a/src/libCStreamedXML/types.h +++ b/src/libCStreamedXML/types.h @@ -244,7 +244,7 @@ struct csxml { const char* elemName = ctx->elemAttrNames.data[i].data; // get attribute value - const char* elemValue = ctx->elemAttrValues.data[i].data; + const char* elemValue = ctx->elemAttrVals.data[i].data; In the case of an empty element, the closeTag() callback will be called immediately afterwards. From bf2ca8d92520e2cfcae3c3c4fbdbcf9ab8e6b11d Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Wed, 4 Oct 2006 10:48:15 +0100 Subject: [PATCH 14/18] Bump version --- src/libCStreamedXML/soversion | 2 +- src/libStreamedXML/soversion | 2 +- version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion index 09c7a32..29bdd8b 100644 --- a/src/libCStreamedXML/soversion +++ b/src/libCStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=0 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=2 +SOMICRO=3 diff --git a/src/libStreamedXML/soversion b/src/libStreamedXML/soversion index a12fb52..c4c84a8 100644 --- a/src/libStreamedXML/soversion +++ b/src/libStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=1 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=2 +SOMICRO=3 diff --git a/version b/version index e495b19..dd61a7e 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=4 +VERMICRO=5 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From 593bb8d80c3c4e678cf0433d1311ba8eb4a6e46d Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Thu, 26 Oct 2006 11:32:08 +0100 Subject: [PATCH 15/18] Fix error where first character of entity name in entity reference was sent to the wrong buffer, and ended up in content rather than entity name. --- src/libCStreamedXML/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c index cffb56a..b0f4615 100644 --- a/src/libCStreamedXML/parser.c +++ b/src/libCStreamedXML/parser.c @@ -550,7 +550,7 @@ int csxml_feedChar(struct csxml* ctx, char ch) ctx->state = StateCharEntity; ctx->entityChar = 0; } else if(c == ClassNameStartChar) { - APPEND_CH(buffer, ch); + APPEND_CH(buffer2, ch); ctx->state = StateEntityName; } else ERROR("Invalid entity name."); break; From 2f2e07b2e272c2a9d161db70ec1dfe69238014e1 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Thu, 26 Oct 2006 11:32:34 +0100 Subject: [PATCH 16/18] Bump version --- src/libCStreamedXML/soversion | 2 +- version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion index 29bdd8b..8a16674 100644 --- a/src/libCStreamedXML/soversion +++ b/src/libCStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=0 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=3 +SOMICRO=4 diff --git a/version b/version index dd61a7e..995c148 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=5 +VERMICRO=6 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From f7fe4bb787927c3e20b585cb23bf0da35625bee1 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Thu, 26 Oct 2006 11:45:11 +0100 Subject: [PATCH 17/18] Another bugfix for entity lookups --- src/libCStreamedXML/parser.c | 1 + src/libCStreamedXML/soversion | 2 +- version | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c index b0f4615..7efea85 100644 --- a/src/libCStreamedXML/parser.c +++ b/src/libCStreamedXML/parser.c @@ -550,6 +550,7 @@ int csxml_feedChar(struct csxml* ctx, char ch) ctx->state = StateCharEntity; ctx->entityChar = 0; } else if(c == ClassNameStartChar) { + CLEAR_BUFFER(buffer2); APPEND_CH(buffer2, ch); ctx->state = StateEntityName; } else ERROR("Invalid entity name."); diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion index 8a16674..6ed55ca 100644 --- a/src/libCStreamedXML/soversion +++ b/src/libCStreamedXML/soversion @@ -14,4 +14,4 @@ SOMAJOR=0 SOMINOR=0 # SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=4 +SOMICRO=5 diff --git a/version b/version index 995c148..24ddb1e 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=6 +VERMICRO=7 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4; From 0a86b2d57fffd6080bce1a920b6dea642388a6aa Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Thu, 23 Nov 2006 00:17:46 +0000 Subject: [PATCH 18/18] Release 1.2.8 (split out libCStreamedXML) --- README | 8 +- src/ctests/.params | 1 - src/ctests/build.default | 3 - src/ctests/build.tests | 43 -- src/ctests/cCallback.c | 137 ----- src/ctests/template | 35 -- src/libCStreamedXML/.params | 1 - src/libCStreamedXML/BottomHeader.h | 14 - src/libCStreamedXML/TopHeader.h | 32 -- src/libCStreamedXML/TopSource.c | 20 - src/libCStreamedXML/buffer.c | 100 ---- src/libCStreamedXML/build.default | 1 - src/libCStreamedXML/build.install | 1 - src/libCStreamedXML/build.install-lib | 36 -- src/libCStreamedXML/build.lib | 51 -- src/libCStreamedXML/build.monolithic | 21 - src/libCStreamedXML/defaults.c | 79 --- src/libCStreamedXML/functions.h | 102 ---- src/libCStreamedXML/parser.c | 693 -------------------------- src/libCStreamedXML/pkgconf.in | 21 - src/libCStreamedXML/soversion | 17 - src/libCStreamedXML/types.h | 322 ------------ version | 2 +- 23 files changed, 7 insertions(+), 1733 deletions(-) delete mode 100644 src/ctests/.params delete mode 100644 src/ctests/build.default delete mode 100644 src/ctests/build.tests delete mode 100644 src/ctests/cCallback.c delete mode 100644 src/ctests/template delete mode 100644 src/libCStreamedXML/.params delete mode 100644 src/libCStreamedXML/BottomHeader.h delete mode 100644 src/libCStreamedXML/TopHeader.h delete mode 100644 src/libCStreamedXML/TopSource.c delete mode 100644 src/libCStreamedXML/buffer.c delete mode 100644 src/libCStreamedXML/build.default delete mode 100644 src/libCStreamedXML/build.install delete mode 100644 src/libCStreamedXML/build.install-lib delete mode 100644 src/libCStreamedXML/build.lib delete mode 100644 src/libCStreamedXML/build.monolithic delete mode 100644 src/libCStreamedXML/defaults.c delete mode 100644 src/libCStreamedXML/functions.h delete mode 100644 src/libCStreamedXML/parser.c delete mode 100644 src/libCStreamedXML/pkgconf.in delete mode 100644 src/libCStreamedXML/soversion delete mode 100644 src/libCStreamedXML/types.h 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/src/ctests/.params b/src/ctests/.params deleted file mode 100644 index 5dcd0de..0000000 --- a/src/ctests/.params +++ /dev/null @@ -1 +0,0 @@ -c tests ctests libCStreamedXML diff --git a/src/ctests/build.default b/src/ctests/build.default deleted file mode 100644 index 183fd69..0000000 --- a/src/ctests/build.default +++ /dev/null @@ -1,3 +0,0 @@ -source src/ctests/build.tests -# kate: replace-trailing-space-save true; space-indent true; tab-width 4; -# vim: expandtab:ts=4:sw=4 diff --git a/src/ctests/build.tests b/src/ctests/build.tests deleted file mode 100644 index ebf1a82..0000000 --- a/src/ctests/build.tests +++ /dev/null @@ -1,43 +0,0 @@ -# These are external variables, and shouldn't clash with anything else -# ctests_BUILT -# - -build_target libCStreamedXML || return 1 - -if [ -z ${ctests_BUILT} ] -then - LIBS="${libCStreamedXML} " - EXTRAS="" - - echo "Building test programs..." - do_cmd mkdir -p obj/tests || return 1 - - for SRC in src/ctests/*.c - do - TEST="obj/tests/$(basename ${SRC} | sed -e 's,.c$,,')" - MODIFIED=0 - for file in ${LIBS} ${SRC} src/ctests/build.tests - do - if [ ${file} -nt ${TEST} ] - then - MODIFIED=1 - break - fi - done - - if [ ${MODIFIED} -ne 0 ] - then - do_cmd ${CC} -Iobj ${CFLAGS} -o ${TEST} ${SRC} ${LIBS} ${EXTRAS} || return 1 - print_success "Built ${TEST}" - else - print_success "${TEST} is up to date" - fi - done - - print_success "All tests built" - - ctests_BUILT=1 -fi - -# kate: replace-trailing-space-save true; space-indent true; tab-width 4; -# vim: expandtab:ts=4:sw=4 diff --git a/src/ctests/cCallback.c b/src/ctests/cCallback.c deleted file mode 100644 index 0540df3..0000000 --- a/src/ctests/cCallback.c +++ /dev/null @@ -1,137 +0,0 @@ -/* libStreamedXML/src/ctests/cCallback.c - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -#include "StreamedXML.h" - -#include -#include - - - -int echo_whiteSpace(const struct csxml* ctx, const char* ws) -{ - (void)ctx; - printf("Whitespace: ``%s''\n", ws); - return 0; -} - -int echo_content(const struct csxml* ctx, const char* data) -{ - (void)ctx; - printf("Content: ``%s''\n", data); - return 0; -} - -int echo_cdata(const struct csxml* ctx, const char* data) -{ - (void)ctx; - printf("CDATA: ``%s''\n", data); - return 0; -} - -int echo_streamRestart(const struct csxml* ctx, const char* data) -{ - (void)ctx; - printf("Stream restart marker: ``%s''\n", data); - return 0; -} - -int echo_PI(const struct csxml* ctx, const char* target, const char* data) -{ - (void)ctx; - printf("PI: target ``%s'', data ", target); - if(data) printf("``%s''\n", data); - else printf("not specified\n"); - return 0; -} - -int echo_comment(const struct csxml* ctx, const char* data) -{ - (void)ctx; - printf("Comment: ``%s''\n", data); - return 0; -} - -int echo_element(const struct csxml* ctx, const char* elemName, int numAttrs) -{ - int i; - - printf("Open tag: <%s> (%d attributes)\n", elemName, numAttrs); - for(i = 0; i < numAttrs; ++i) printf(" %s='%s'\n", ctx->elemAttrNames.data[i].data, ctx->elemAttrVals.data[i].data); - return 0; -} - -int echo_closeTag(const struct csxml* ctx, const char* elemName) -{ - (void)ctx; - printf("Close tag: \n", elemName); - return 0; -} - -const char* echo_entityRef(const struct csxml* ctx, const char* ent) -{ - (void)ctx; - printf("Entity reference: ``%s''\n", ent); - return 0; -} - - - -int main(int argc, char* argv[]) -{ - FILE* fp = 0; - char buf[1024]; - size_t amt; - struct csxml* ctx = 0; - - if(argc == 2 && !strcmp(argv[1], "--print-summary")) { - printf("{C library} Tests the callback functions.\n"); - return 0; - } - - if(argc != 2) { - fprintf(stderr, "Expecting filename.\n"); - return 1; - } - - fp = fopen(argv[1], "r"); - if(!fp) { - fprintf(stderr, "Error opening '%s' for input.\n", argv[1]); - return 1; - } - - ctx = csxml_newParser(); - if(!ctx) { - fprintf(stderr, "Couldn't allocate a new parser.\n"); - return 1; - } - - ctx->whiteSpace = echo_whiteSpace; - ctx->content = echo_content; - ctx->cdata = echo_cdata; - ctx->streamRestart = echo_streamRestart; - ctx->PI = echo_PI; - ctx->comment = echo_comment; - ctx->element = echo_element; - ctx->closeTag = echo_closeTag; - ctx->entityRef = echo_entityRef; - - while(!feof(fp)) { - amt = fread(buf, 1, sizeof(buf), fp); - csxml_feedData(ctx, buf, amt); - } - - csxml_freeParser(ctx); - fclose(fp); - - return 0; -} - -/* 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/ctests/template b/src/ctests/template deleted file mode 100644 index a829314..0000000 --- a/src/ctests/template +++ /dev/null @@ -1,35 +0,0 @@ -/* libStreamedXML/src/ctests/???.c - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -#include "StreamedXML.h" - -#include - - - -int main(int argc, char* argv[]) -{ - if(argc == 2 && !strcmp(argv[1], "--print-summary")) { - printf("One line summary.\n"); - return 0; - } - - if(argc == 1) { - // empty argument list - } - - int ret = 0; - - // TODO - - return ret; -} - -/* 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/libCStreamedXML/.params b/src/libCStreamedXML/.params deleted file mode 100644 index eca3504..0000000 --- a/src/libCStreamedXML/.params +++ /dev/null @@ -1 +0,0 @@ -c lib libCStreamedXML StreamedXML.h diff --git a/src/libCStreamedXML/BottomHeader.h b/src/libCStreamedXML/BottomHeader.h deleted file mode 100644 index 3034856..0000000 --- a/src/libCStreamedXML/BottomHeader.h +++ /dev/null @@ -1,14 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/BottomHeader.h - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -#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/libCStreamedXML/TopHeader.h b/src/libCStreamedXML/TopHeader.h deleted file mode 100644 index 729d936..0000000 --- a/src/libCStreamedXML/TopHeader.h +++ /dev/null @@ -1,32 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/TopHeader.h - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -#ifndef HEADER_libCStreamedXML -#define HEADER_libCStreamedXML - -// standard includes, or includes needed for type declarations -#include - -/*! \defgroup libCStreamedXML libCStreamedXML interface. - -libCStreamedXML is a C library for parsing Streamed XML data. It is somewhat simpler than the C++ -library (it only parses ASCII data, not Unicode data). In future, the API could be extended to -use only fixed-size buffers, and not to call malloc() at all. This would be advantageous for small -embedded systems (e.g. PICs). - -To parse Streamed XML, you must first create a parser context object with csxml_newParser(). Then -you set up the returned object by changing options and callback functions. Once set up correctly, -pass in data using the csxml_feedChar() and csxml_feedData() functions. Finally, free the parser -object with csxml_freeParser(). - -*/ -/*!@{*/ - -/* 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/libCStreamedXML/TopSource.c b/src/libCStreamedXML/TopSource.c deleted file mode 100644 index 90d401c..0000000 --- a/src/libCStreamedXML/TopSource.c +++ /dev/null @@ -1,20 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXMLlibCStreamedXML/TopSource.c - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -#include "StreamedXML.h" - -// Below are all the includes used throughout the library. -#include -#include -#include - -//#define DEBUG_STATE_MACHINE - -/* 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/libCStreamedXML/buffer.c b/src/libCStreamedXML/buffer.c deleted file mode 100644 index 10cab8a..0000000 --- a/src/libCStreamedXML/buffer.c +++ /dev/null @@ -1,100 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/buffer.c - * - * (c)2006, Laurence Withers. Released under the GNU GPL. See file - * COPYING for more information / terms of license. -*/ - -static int do_realloc(struct csxml* ctx, struct csxml_buf* buf) -{ - char* n = realloc(buf->data, buf->size << 1); - if(!n) { - ctx->outOfMemory(ctx, buf->size << 1); - return -1; - } - - buf->size <<= 1; - buf->data = n; - return 0; -} - -static int buffer_copy(struct csxml* ctx, struct csxml_buf* dest, const struct csxml_buf* src) -{ - while(dest->size <= src->len) if(do_realloc(ctx, dest)) return -1; - strcpy(dest->data, src->data); - dest->len = src->len; - return 0; -} - -static int buffer_strcat(struct csxml* ctx, struct csxml_buf* dest, const char* src) -{ - size_t req = strlen(src) + dest->len; - while(req >= dest->size) if(do_realloc(ctx, dest)) return -1; - strcat(dest->data, src); - return 0; -} - -static int buffer_init(struct csxml* ctx, struct csxml_buf* buf) -{ - memset(buf, 0, sizeof(buf)); - buf->size = 256; - buf->data = malloc(buf->size); - if(!buf->data) { - ctx->outOfMemory(ctx, buf->size); - return -1; - } - return 0; -} - -static void buffer_free(struct csxml_buf* buf) -{ - free(buf->data); - memset(buf, 0, sizeof(struct csxml_buf)); -} - -static int do_realloc2(struct csxml* ctx, struct csxml_list* list) -{ - size_t i, newlen = list->size ? (list->size << 1) : 4; - struct csxml_buf* n = realloc(list->data, newlen * sizeof(struct csxml_buf)); - if(!n) { - ctx->outOfMemory(ctx, newlen * sizeof(struct csxml_buf)); - return -1; - } - - memset(n + list->size * sizeof(struct csxml_buf), 0, newlen * sizeof(struct csxml_buf)); - for(i = 0; i < newlen; ++i) { - if(buffer_init(ctx, n + list->size + i)) return -1; - } - - list->size = newlen; - list->data = n; - return 0; -} - -static int list_push(struct csxml* ctx, struct csxml_list* list, struct csxml_buf* buf) -{ - if((list->size == list->len) && do_realloc2(ctx, list)) return -1; - if(buffer_copy(ctx, list->data + list->len, buf)) return -1; - ++list->len; - return 0; -} - -static struct csxml_buf* list_pop(struct csxml_list* list) -{ - return list->data + --list->len; -} - -static void list_free(struct csxml_list* list) -{ - size_t i; - - for(i = 0; i < list->size; ++i) buffer_free(list->data + i); - free(list->data); - memset(list, 0, sizeof(struct csxml_list)); -} - - - -/* 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/libCStreamedXML/build.default b/src/libCStreamedXML/build.default deleted file mode 100644 index a24840e..0000000 --- a/src/libCStreamedXML/build.default +++ /dev/null @@ -1 +0,0 @@ -source src/libCStreamedXML/build.lib diff --git a/src/libCStreamedXML/build.install b/src/libCStreamedXML/build.install deleted file mode 100644 index a8df5b5..0000000 --- a/src/libCStreamedXML/build.install +++ /dev/null @@ -1 +0,0 @@ -source src/libCStreamedXML/build.install-lib diff --git a/src/libCStreamedXML/build.install-lib b/src/libCStreamedXML/build.install-lib deleted file mode 100644 index beec81b..0000000 --- a/src/libCStreamedXML/build.install-lib +++ /dev/null @@ -1,36 +0,0 @@ -build_target libCStreamedXML - -# make paths (this is for Gentoo in particular) -build_dir_tree "${LIBDIR}" || return 1 -build_dir_tree "${PKGCONFDIR}" || return 1 -build_dir_tree "${INCLUDEDIR}" || return 1 - -# install library -echo "Installing libraries into '${LIBDIR}'" -install_file ${libCStreamedXML} ${LIBDIR} 0755 || return 1 -BASE="${libCStreamedXML_BASE}.so" -MAJOR="${BASE}.${SOMAJOR}" -MINOR="${MAJOR}.${SOMINOR}" -MICRO="${MINOR}.${SOMICRO}" -install_symlink "${MINOR}" "${MICRO}" "${LIBDIR}" -install_symlink "${MAJOR}" "${MINOR}" "${LIBDIR}" -install_symlink "${BASE}" "${MAJOR}" "${LIBDIR}" - -# install header -echo "Installing header file '${libCStreamedXML_HEADER}' into ${INCLUDEDIR}" -install_header ${libCStreamedXML_HEADER} ${INCLUDEDIR} 0644 || return 1 - -# install pkgconfig file -echo "Installing package config file into ${PKGCONFDIR}" -PKGCONFFILE=${PKGCONFDIR}/libCStreamedXML.pc -do_cmd rm -f ${PKGCONFFILE} -do_cmd_redir ${PKGCONFFILE} sed \ - -e "s,@VERSION@,${VERSION}," \ - -e "s,@LIBDIR@,${FINALLIBDIR}," \ - -e "s,@INCLUDEDIR@,${FINALINCLUDEDIR}," \ - src/libCStreamedXML/pkgconf.in -do_cmd chmod 0644 ${PKGCONFFILE} -print_success "Done" - -# kate: replace-trailing-space-save true; space-indent true; tab-width 4; -# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/build.lib b/src/libCStreamedXML/build.lib deleted file mode 100644 index 2b86961..0000000 --- a/src/libCStreamedXML/build.lib +++ /dev/null @@ -1,51 +0,0 @@ -# These are external variables, and shouldn't clash with anything else -# libCStreamedXML -# libCStreamedXML_BUILT -# libCStreamedXML_HEADER -# libCStreamedXML_BASE - -if [ -z ${libCStreamedXML_BUILT} ] -then - libCStreamedXML_BASE=libCStreamedXML - source src/libCStreamedXML/soversion - - libCStreamedXML="obj/${libCStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}.${SOMICRO}" - SO_EXTRA="-lc" # @TODO@ libs, cflags - - echo "Building library ${libCStreamedXML}..." - - do_cmd source src/libCStreamedXML/build.monolithic || return 1 - - MODIFIED=0 - for test in ${MONOLITHIC_TESTS} ${HDR} ${SRC} - do - if [ ${test} -nt ${libCStreamedXML} ] - then - MODIFIED=1 - break - fi - done - - if [ ${MODIFIED} -ne 0 ] - then - echo " Compiling" - - SONAME="${libCStreamedXML_BASE}.so.${SOMAJOR}.${SOMINOR}" - do_cmd ${CC} ${CFLAGS} -Iobj -shared -fpic -o "${libCStreamedXML}" \ - -Wl,-soname,${SONAME} \ - ${SRC} ${SO_EXTRA} || return 1 - - # make tests work - do_cmd ln -sf $(basename ${libCStreamedXML}) obj/${SONAME} || return 1 - - print_success "Library built" - else - print_success "Library up to date" - fi - - libCStreamedXML_BUILT=1 - libCStreamedXML_HEADER=${HDR} - -fi -# kate: replace-trailing-space-save true; space-indent true; tab-width 4; -# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/build.monolithic b/src/libCStreamedXML/build.monolithic deleted file mode 100644 index 733082a..0000000 --- a/src/libCStreamedXML/build.monolithic +++ /dev/null @@ -1,21 +0,0 @@ -# These are external variables, and shouldn't clash with anything else -# libCStreamedXML_MONOLITHIC - -SRC="obj/libCStreamedXML.c" -HDR="obj/StreamedXML.h" - -MONOLITHIC_TESTS="src/libCStreamedXML/build.lib src/libCStreamedXML/build.monolithic" - -if [ -z "${libCStreamedXML_MONOLITHIC}" ] -then - MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopHeader,types,functions,BottomHeader}.h)" - make_monolithic ${HDR} Ch || return 1 - - MONOLITHIC_SOURCE="$(echo src/libCStreamedXML/{TopSource,buffer,defaults,parser}.c)" - make_monolithic ${SRC} C || return 1 - - libCStreamedXML_MONOLITHIC=1 - MONOLITHIC_DOC="${MONOLITHIC_DOC} ${HDR}" -fi -# kate: replace-trailing-space-save true; space-indent true; tab-width 4; -# vim: expandtab:ts=4:sw=4 diff --git a/src/libCStreamedXML/defaults.c b/src/libCStreamedXML/defaults.c deleted file mode 100644 index a02e2f1..0000000 --- a/src/libCStreamedXML/defaults.c +++ /dev/null @@ -1,79 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/defaults.c - * - * (c)2006, Laurence Withers. Released under the GNU GPL. See file - * COPYING for more information / terms of license. -*/ - -static void default_notWellFormed(const struct csxml* ctx, const char* reason) -{ - fprintf(stderr, "Streamed XML is not well formed.\n Line : %d\n Col : %d\n Reason: %s\n", - ctx->line + 1, ctx->col + 1, reason); -} - - - -static void default_outOfMemory(const struct csxml* ctx, size_t amount) -{ - (void)ctx; - fprintf(stderr, "Streamed XML parser: out of memory allocating %lu bytes\n", (unsigned long)amount); -} - - - -static void default_unknownEntity(const struct csxml* ctx, const char* ent) -{ - fprintf(stderr, "Unknown entity referenced in Streamed XML.\n Line: %d\n Col : %d\n Name: %s\n", - ctx->line + 1, ctx->col + 1, ent); -} - - - -static int default_discard(const struct csxml* ctx, const char* x) -{ - (void)ctx; - (void)x; - return 0; -} - - - -static int default_cdata(const struct csxml* ctx, const char* data) -{ - return ctx->content(ctx, data); -} - - - -static int default_discardPI(const struct csxml* ctx, const char* target, const char* data) -{ - (void)ctx; - (void)target; - (void)data; - return 0; -} - - - -static int default_discardElem(const struct csxml* ctx, const char* elemName, int numAttrs) -{ - (void)ctx; - (void)elemName; - (void)numAttrs; - return 0; -} - - - -static const char* default_discardEnt(const struct csxml* ctx, const char* ent) -{ - (void)ctx; - (void)ent; - return 0; -} - - - -/* 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/libCStreamedXML/functions.h b/src/libCStreamedXML/functions.h deleted file mode 100644 index 9075ba9..0000000 --- a/src/libCStreamedXML/functions.h +++ /dev/null @@ -1,102 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/types.h - * - * (c)2006, Laurence Withers. Released under the GNU GPL. See file - * COPYING for more information / terms of license. -*/ - - - -/*! \brief Allocate and set up a new parser object. - -\retval 0 on error (see \a errno). -\returns Pointer to newly-allocated parser object. - -Call this function to obtain a parser context object. The object is initially populated with -sensible defaults (\a expandEntities is 1, the error callback functions print messages to stderr, -the data callback functions discard the data, etc.). - -*/ -struct csxml* csxml_newParser(); - - - -/*! \brief Free an existing parser object. - -\param ctx The object to free (may be 0). - -Frees a parser object and all of its associated data structures (strings, lists, etc.). - -*/ -void csxml_freeParser(struct csxml* ctx); - - - -/*! \brief Parse a character. - -\param ctx Parser context. -\param ch Character to parse. -\retval 0 on success. -\retval -1 on XML error. -\retval (non-0) if any callback function signals an error. - -This function parses a single character. It will generate callbacks as appropriate. If one of the -callback functions returns a non-zero value, that value is returned from this function and the -object is put into an error state. If the streamed XML is not well formed, or some other parsing -error occurs, -1 will be returned and the object will be put into an error state. - -Once in an error state, the function will simply discard data passed to it and return 0. However, -a lower-level parser is still running and is capable of matching stream restart markers, allowing -the parser to be reset. - -*/ -int csxml_feedChar(struct csxml* ctx, char ch); - - - -/*! \brief Look up an entity. - -\param ctx Parser context. -\param ent Entity name. -\retval 0 on error. -\returns Pointer to null-terminated string of expanded entity text. - -This function is called to dereference entities. It handles the standard entities itself, and chains -on to the entityRef callback of the parser if needed. If the entity is not found, it calls the -unknownEntity callback and returns 0. - -*/ -const char* csxml_entityRef(struct csxml* ctx, const char* ent); - - - -/*! \brief Reset parser. - -\param ctx Parser context. - -This function will reset the parser into its initial state, as though no data had yet been -encountered. This is called after stream restart markers for example. - -*/ -void csxml_reset(struct csxml* ctx); - - - - -/*! \brief Parse a block of data. - -\param ctx Parser context. -\param data Pointer to block of data. -\param amt Number of bytes to parse. - -This function will parse each character in the block of data. If an error is encountered, the usual -process (callback, error state) is followed, but this function will continue to feed in data. The -idea is that you continue to feed in data from your data source, which might have a restart marker -(at which point the parsing will once again continue). - -*/ -void csxml_feedData(struct csxml* ctx, const char* data, size_t amt); - -/* 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/libCStreamedXML/parser.c b/src/libCStreamedXML/parser.c deleted file mode 100644 index 7efea85..0000000 --- a/src/libCStreamedXML/parser.c +++ /dev/null @@ -1,693 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/parser.c - * - * (c)2006, Laurence Withers. Released under the GNU GPL. See file - * COPYING for more information / terms of license. -*/ - -//#define DEBUG_STATE_MACHINE - -#ifdef DEBUG_STATE_MACHINE -#include -#endif - -#include -#include -#include - - - -enum csxml_State { - StateNone, // at element or stream level - StateRestartMarker, // after ', '?' - ClassOther, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // '@', 'A'--'C' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'D'--'G' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'H'--'K' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'L'--'O' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'P'--'S' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'T'--'W' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassOther, // 'X'--'Z', '[' - ClassOther, ClassOther, ClassOther, ClassNameStartChar, // '\\', ']', '^', '_' - ClassOther, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // '`', 'a'--'c' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'd'--'g' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'h'--'k' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'l'--'o' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 'p'--'s' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, // 't'--'w' - ClassNameStartChar, ClassNameStartChar, ClassNameStartChar, ClassOther, // 'x'--'z', '{' - ClassOther, ClassOther, ClassOther, ClassInvalid // '|', '}', '~', control 7F -}; - - - -int csxml_feedChar(struct csxml* ctx, char ch) -{ - enum TokenClass c; - int try; - -#ifdef DEBUG_STATE_MACHINE - printf("%p: Character '%c' (%02X), state %d, buffer %s\n", ctx, ch, ch, ctx->state, ctx->buffer.data); -#endif - -#define ERROR(_reason) do { \ - ctx->state = StateError; \ - ctx->notWellFormed(ctx, _reason); \ - return -1; \ -}while(0) - -#define APPEND_CH(_whichbuf, _ch) do { \ - ctx-> _whichbuf .data[ctx-> _whichbuf .len++] = _ch; \ - if((ctx-> _whichbuf .len == ctx-> _whichbuf .size) && \ - do_realloc(ctx, &ctx-> _whichbuf)) return -1; \ - ctx-> _whichbuf .data[ctx-> _whichbuf .len] = 0; \ -}while(0) - -#define CLEAR_BUFFER(_whichbuf) do { \ - ctx-> _whichbuf .data[0] = 0; \ - ctx-> _whichbuf .len = 0; \ -}while(0) - -#define TRY(_x) do { \ - try = (_x); \ - if(try) { \ - ctx->state = StateError; \ - return try; \ - } \ -}while(0) - - if(ch == xmlRestartMarker[ctx->restartCount]) { - if(++ctx->restartCount == 11) { - ctx->state = StateRestartMarker; - csxml_reset(ctx); - return 0; - } - } else { - ctx->restartCount = 0; - } - - if(ch & ~0x7F) c = ClassInvalid; - else c = token_classes[(int)ch]; - - if(ch == '\r') { - ctx->skipNextNewline = 1; - ch = '\n'; - ++ctx->line; - ctx->col = 0; - } else if(ch == '\n') { - if(ctx->skipNextNewline) return 0; - ++ctx->line; - ctx->col = 0; - } else { - ctx->skipNextNewline = 0; - } - - if(c == ClassInvalid) ERROR("Restricted character encountered."); - - // deal with char appropriately, according to state - switch(ctx->state) { - case StateError: - return 0; - - case StateNone: - switch(c) { - case ClassWhitespace: - APPEND_CH(buffer, ch); - break; - - case ClassOpenTag: - ctx->state = StateOpen; - if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - break; - - case ClassEntity: - if(ctx->expandEntities) { - if(!ctx->elementDepth) ERROR("Entities cannot appear at stream level."); - if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - ctx->parsingAttr = 0; - ctx->state = StateEntity; - break; - } - - // fall through - default: - if(!ctx->elementDepth) ERROR("Content cannot appear at stream level."); - ctx->state = StateData; - if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - APPEND_CH(buffer, ch); - break; - } - break; - - case StateData: - switch(c) { - case ClassOpenTag: - ctx->state = StateOpen; - TRY(ctx->content(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - break; - - case ClassEntity: - ctx->parsingAttr = 0; - ctx->state = StateEntity; - break; - - default: - APPEND_CH(buffer, ch); - break; - } - break; - - case StateCDATA: - if(ch == ']') ctx->state = StateCDATA1; - else APPEND_CH(buffer, ch); - break; - - case StateCDATA1: - if(ch == ']') ctx->state = StateCDATA2; - else { - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ch); - ctx->state = StateCDATA; - } - break; - - case StateCDATA2: - if(ch == '>') { - ctx->state = StateNone; - TRY(ctx->cdata(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - } else if(ch == ']') { - APPEND_CH(buffer, ']'); - } else { - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ch); - ctx->state = StateCDATA; - } - break; - - case StateRestartMarker: - if(ch == ']') ctx->state = StateRestartMarker1; - else APPEND_CH(buffer, ch); - break; - - case StateRestartMarker1: - if(ch == ']') ctx->state = StateRestartMarker2; - else { - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ch); - ctx->state = StateRestartMarker; - } - break; - - case StateRestartMarker2: - if(ch == '>') { - TRY(ctx->streamRestart(ctx, ctx->buffer.data)); - csxml_reset(ctx); - - } else if(ch == ']') { - APPEND_CH(buffer, ']'); - - } else { - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ']'); - APPEND_CH(buffer, ch); - ctx->state = StateRestartMarker; - } - break; - - case StateOpen: - switch(c) { - case ClassNameStartChar: - ctx->state = StateElemName; - ctx->elemAttrNames.len = 0; - ctx->elemAttrVals.len = 0; - CLEAR_BUFFER(elemName); - APPEND_CH(elemName, ch); - break; - - default: - if(ch == '!') ctx->state = StateOpenBang; - else if(ch == '?') { - ctx->state = StatePI; - CLEAR_BUFFER(buffer2); - } else if(ch == '/') { - if(!ctx->elementDepth) ERROR("Encountered a close tag at stream level."); - ctx->state = StateClose; - } else ERROR("Invalid start character for element."); - break; - } - break; - - case StatePI: - if(ch == '?') ctx->state = StatePI2; - else if(c == ClassWhitespace) { - ctx->state = StatePIData; - CLEAR_BUFFER(buffer); - } else APPEND_CH(buffer2, ch); - break; - - case StatePI2: - if(ch != '>') ERROR("Invalid target for PI"); - else { - ctx->state = StateNone; - TRY(ctx->PI(ctx, ctx->buffer2.data, 0)); - } - break; - - case StatePIData: - if(ch == '?') ctx->state = StatePI3; - else APPEND_CH(buffer, ch); - break; - - case StatePI3: - if(ch == '>') { - ctx->state = StateNone; - TRY(ctx->PI(ctx, ctx->buffer2.data, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - } else if(ch == '?') { - APPEND_CH(buffer, '?'); - } else { - APPEND_CH(buffer, '?'); - APPEND_CH(buffer, ch); - ctx->state = StatePIData; - } - break; - - case StateOpenBang: - if(ch == '[') { - // restart markers handled by lower layer - ctx->state = StateOpenCdataMarker; - ctx->xmlCount = 3; - if(!ctx->elementDepth) ERROR("CDATA sections not valid at stream level."); - } else if(ch == '-') ctx->state = StateOpenComment; - else ERROR("Invalid special tag."); - break; - - case StateOpenCdataMarker: - if(ch != xmlCdataMarker[ctx->xmlCount]) ERROR("Invalid marked section."); - if(!xmlCdataMarker[++ctx->xmlCount]) ctx->state = StateCDATA; - break; - - case StateOpenComment: - if(ch != '-') ERROR("Invalid special tag."); - ctx->state = StateComment; - CLEAR_BUFFER(buffer); - break; - - case StateComment: - if(ch == '-') ctx->state = StateComment2; - else APPEND_CH(buffer, ch); - break; - - case StateComment2: - if(ch == '-') ctx->state = StateComment3; - else { - APPEND_CH(buffer, '-'); - APPEND_CH(buffer, ch); - ctx->state = StateComment; - } - break; - - case StateComment3: - if(ch != '>') ERROR("`--' not valid in comments"); - ctx->state = StateNone; - TRY(ctx->comment(ctx, ctx->buffer.data)); - CLEAR_BUFFER(buffer); - break; - - case StateElemName: - switch(c) { - case ClassWhitespace: - ctx->state = StateElemTag; - CLEAR_BUFFER(buffer); - break; - - case ClassNameStartChar: - case ClassNameChar: - APPEND_CH(elemName, ch); - break; - - default: - switch(ch) { - case L'>': - CLEAR_BUFFER(buffer); - TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - ctx->state = StateNone; - TRY(ctx->element(ctx, ctx->elemName.data, 0)); - ++ctx->elementDepth; - break; - - case L'/': - ctx->state = StateNeedClose; - break; - - default: - ERROR("Invalid character in tag name."); - } - } - break; - - case StateElemTag: - switch(c) { - case ClassWhitespace: - break; - - case ClassNameStartChar: - ctx->state = StateElemAttrName; - CLEAR_BUFFER(buffer); - APPEND_CH(buffer, ch); - break; - - default: - switch(ch) { - case '>': - TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - ctx->state = StateNone; - TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len)); - ++ctx->elementDepth; - break; - - case '/': - ctx->state = StateNeedClose; - break; - - default: - ERROR("Invalid character in tag."); - } - } - break; - - case StateElemAttrName: - switch(c) { - case ClassNameStartChar: - case ClassNameChar: - APPEND_CH(buffer, ch); - break; - - default: - if(ch != '=') ERROR("Invalid character in attribute name."); - TRY(list_push(ctx, &ctx->elemAttrNames, &ctx->buffer)); - CLEAR_BUFFER(buffer); - ctx->state = StateElemAttrEq; - break; - } - break; - - case StateElemAttrEq: - if(ch == '\'') ctx->singleQuote = 1; - else if(ch == '"') ctx->singleQuote = 0; - else ERROR("Invalid character in attribute."); - ctx->state = StateElemAttrVal; - break; - - case StateElemAttrVal: - if((ctx->singleQuote && ch == '\'') || (!ctx->singleQuote && ch == '"')) { - TRY(list_push(ctx, &ctx->elemAttrVals, &ctx->buffer)); - ctx->state = StateElemAttrDone; - } else if(ctx->expandEntities && ch == L'&') { - ctx->parsingAttr = 1; - ctx->state = StateEntity; - } else APPEND_CH(buffer, ch); - break; - - case StateElemAttrDone: - switch(c) { - case ClassWhitespace: - ctx->state = StateElemTag; - break; - - default: - if(ch == '/') { - ctx->state = StateNeedClose; - } else if(ch == '>') { - ctx->state = StateNone; - CLEAR_BUFFER(buffer); - TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); - TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName)); - ++ctx->elementDepth; - } else ERROR("Invalid character after attribute."); - break; - } - break; - - case StateNeedClose: - if(ch != '>') ERROR("Stray `/' in open tag."); - ctx->state = StateNone; - CLEAR_BUFFER(buffer); - TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len)); - TRY(ctx->closeTag(ctx, ctx->elemName.data)); - break; - - case StateClose: - if(c != ClassNameStartChar) ERROR("Invalid character in close tag name."); - APPEND_CH(buffer, ch); - ctx->state = StateClosing; - break; - - case StateClosing: - switch(c) { - case ClassNameStartChar: - case ClassNameChar: - APPEND_CH(buffer, ch); - break; - - case ClassWhitespace: - ctx->state = StateNeedClose2; - break; - - default: - if(ch != '>') ERROR("Invalid character in close tag name."); - TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); - if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); - ctx->state = StateNone; - CLEAR_BUFFER(buffer); - TRY(ctx->closeTag(ctx, ctx->elemName.data)); - --ctx->elementDepth; - } - break; - - case StateNeedClose2: - if(c == ClassWhitespace) break; - if(ch != '>') ERROR("Invalid data in close tag."); - TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack))); - if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag."); - ctx->state = StateNone; - CLEAR_BUFFER(buffer); - TRY(ctx->closeTag(ctx, ctx->elemName.data)); - --ctx->elementDepth; - break; - - case StateEntity: - if(ch == '#') { - ctx->state = StateCharEntity; - ctx->entityChar = 0; - } else if(c == ClassNameStartChar) { - CLEAR_BUFFER(buffer2); - APPEND_CH(buffer2, ch); - ctx->state = StateEntityName; - } else ERROR("Invalid entity name."); - break; - - case StateCharEntity: - if(ch == ';') { - APPEND_CH(buffer, ctx->entityChar); - ctx->state = ctx->parsingAttr ? StateElemAttrVal : StateData; - break; - - } else if(ch >= '0' && ch <= '9') { - ctx->entityChar *= 10; - ctx->entityChar += (ch - '0'); - if(!ctx->entityChar || ctx->entityChar > 126) ERROR("Character code out of range in character entity."); - } else ERROR("Invalid character in character entity."); - break; - - case StateEntityName: - if(ch == ';') { - const char* e = csxml_entityRef(ctx, ctx->buffer2.data); - TRY(!e || buffer_strcat(ctx, &ctx->buffer, e)); - ctx->state = ctx->parsingAttr ? StateElemAttrVal : StateData; - break; - } - if(c != ClassNameChar && c != ClassNameStartChar) ERROR("Invalid entity name."); - APPEND_CH(buffer2, ch); - break; - } - ++ctx->col; - return 0; -} - - - -const char* csxml_entityRef(struct csxml* ctx, const char* ent) -{ - const char* q = 0; - - if(!strcmp(ent, "quot")) return "\""; - if(!strcmp(ent, "amp")) return "&"; - if(!strcmp(ent, "apos")) return "'"; - if(!strcmp(ent, "lt")) return "<"; - if(!strcmp(ent, "gt")) return ">"; - - q = ctx->entityRef(ctx, ent); - if(!q) { - ctx->state = StateError; - ctx->unknownEntity(ctx, ent); - return 0; - } - - return q; -} - - - -void csxml_reset(struct csxml* ctx) -{ - CLEAR_BUFFER(buffer); - CLEAR_BUFFER(buffer2); - CLEAR_BUFFER(elemName); - ctx->state = StateNone; - ctx->xmlCount = 0; - ctx->elementDepth = 0; - ctx->restartCount = 0; - ctx->skipNextNewline = 0; - ctx->parsingAttr = 0; - ctx->line = 0; - ctx->col = 0; - ctx->elemStack.len = 0; - ctx->elemAttrNames.len = 0; - ctx->elemAttrVals.len = 0; -} - - - -#undef ERROR -#undef APPEND_CH -#undef CLEAR_BUFFER - - - -void csxml_freeParser(struct csxml* ctx) -{ - if(!ctx) return; - buffer_free(&ctx->buffer); - buffer_free(&ctx->buffer2); - buffer_free(&ctx->elemName); - list_free(&ctx->elemStack); - list_free(&ctx->elemAttrNames); - list_free(&ctx->elemAttrVals); -} - - - -struct csxml* csxml_newParser() -{ - struct csxml* ctx = 0; - - ctx = malloc(sizeof(struct csxml)); - if(!ctx) return 0; - memset(ctx, 0, sizeof(struct csxml)); - - if(buffer_init(ctx, &ctx->buffer) || buffer_init(ctx, &ctx->buffer2) || buffer_init(ctx, &ctx->elemName)) { - csxml_freeParser(ctx); - return 0; - } - - ctx->expandEntities = 1; - - ctx->notWellFormed = default_notWellFormed; - ctx->outOfMemory = default_outOfMemory; - ctx->unknownEntity = default_unknownEntity; - ctx->whiteSpace = default_discard; - ctx->content = default_discard; - ctx->cdata = default_cdata; - ctx->streamRestart = default_discard; - ctx->PI = default_discardPI; - ctx->comment = default_discard; - ctx->element = default_discardElem; - ctx->closeTag = default_discard; - ctx->entityRef = default_discardEnt; - - return ctx; -} - - - -void csxml_feedData(struct csxml* ctx, const char* data, size_t amt) -{ - while(amt--) csxml_feedChar(ctx, *data++); -} - - - -/* 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/libCStreamedXML/pkgconf.in b/src/libCStreamedXML/pkgconf.in deleted file mode 100644 index acdb6c5..0000000 --- a/src/libCStreamedXML/pkgconf.in +++ /dev/null @@ -1,21 +0,0 @@ -# libStreamedXML/src/lib/libCStreamedXML/pkgconf.in -# -# Metadata file for pkg-config -# ( http://www.freedesktop.org/software/pkgconfig/ ) -# -# (c)2006, Laurence Withers, . -# Released under the GNU GPLv2. See file COPYING or -# http://www.gnu.org/copyleft/gpl.html for details. -# - -# Name, description -Name: libCStreamedXML -Description: C library for parsing Streamed XML -Version: @VERSION@ - -# Requirements -Requires: - -# Compilation information -Libs: -L@LIBDIR@ -lCStreamedXML -Cflags: -I@INCLUDEDIR@ diff --git a/src/libCStreamedXML/soversion b/src/libCStreamedXML/soversion deleted file mode 100644 index 6ed55ca..0000000 --- a/src/libCStreamedXML/soversion +++ /dev/null @@ -1,17 +0,0 @@ -# libStreamedXML/src/libCStreamedXML/soversion -# -# (c)2006, Laurence Withers, . -# Released under the GNU GPLv2. See file COPYING or -# http://www.gnu.org/copyleft/gpl.html for details. -# - - - -# SOMAJOR and SOMINOR are included in the library's soname. They need to -# be bumped on a binary-incompatible release. They are both single -# integers. -SOMAJOR=0 -SOMINOR=0 - -# SOMICRO is bumped every time there is a binary-compatible release. -SOMICRO=5 diff --git a/src/libCStreamedXML/types.h b/src/libCStreamedXML/types.h deleted file mode 100644 index 16a6ced..0000000 --- a/src/libCStreamedXML/types.h +++ /dev/null @@ -1,322 +0,0 @@ -/* libCStreamedXML/src/libCStreamedXML/types.h - * - * (c)2006, Laurence Withers. Released under the GNU GPL. See file - * COPYING for more information / terms of license. -*/ - - - -/*! \brief String buffer. - -This type implements a simple string buffer. The string should be kept null-terminated. The \a data -pointer is reallocated as necessary (i.e. when \a len becomes equal to \a size). \a len is the -string length (excluding terminating null) and \a size is the size of the allocated buffer. It is -never valid for \a data or \a size to be 0. - -*/ -struct csxml_buf { - /// Pointer to string (null terminated). - char* data; - - /// Length of string (excluding null). - size_t len; - - /// Size of allocated buffer. - size_t size; -}; - - - -/*! \brief String list. - -This type implements a dynamic array of strings (using the struct csxml_buf type). The \a data -pointer is reallocated as necessary (i.e. when \a len becomes equal to \a size). \a len is the -number of valid elements in the array and \a size is the size of the allocated buffer. It is valid -for \a data and \a size to be zero. - -*/ -struct csxml_list { - /// Array of buffers (all allocated elements are valid and initialised). - struct csxml_buf* data; - - /// Number of elements in use. - size_t len; - - /// Number of allocated elements. - size_t size; -}; - - - -/*! \brief Streamed XML parser context. - -This structure contains all the details of a Streamed XML parsing operation. Most fields are -internal to the parser and should not be touched; those are briefly documented here. You may want to -change the \a expandEntities option, examine the \a line and \a col variables, and change the -callback functions. - -Those members marked Internal: are subject to change (either in semantics, type or existence). - -*/ -struct csxml { - /// Option: change "&lt;" to "<", etc. if non-zero (the default). Change to 0 to leave - /// entities inline. - int expandEntities; - - /// Current line (from 0, starts from last restart marker). - int line; - /// Current column (from 0, starts from last restart marker). - int col; - - /// List of attribute names for current element. - struct csxml_list elemAttrNames; - /// List of attribute values for current element. - struct csxml_list elemAttrVals; - - /// User data. - void* user; - - - /*! \brief Error callback: Streamed XML is not well formed. - - \param ctx Parsing context. - \param reason Human-readable description of error. - - This function is called whenever badly-formed Streamed XML is encountered (e.g. if content is - encountered at stream-level). - - The default implementation prints a formatted message to \a stderr. - - */ - void (*notWellFormed)(const struct csxml* ctx, const char* reason); - - - - /*! \brief Error callback: out of memory. - - \param ctx Parsing context. - \param amount Number of bytes we tried to allocate. - - This function is called whenever a dynamic string resizing operation (or similar) fails. It is - called with the number of bytes the library attempted to allocate. - - The default implementation prints a formatted message to \a stderr. - - \todo When parsing extremely long content sections, we could just call the content() callback - when memory is low rather than failing altogether. - - */ - void (*outOfMemory)(const struct csxml* ctx, size_t amount); - - - - /*! \brief Error callback: reference to unknown entity. - - \param ctx Parsing context. - \param ent Name of the referenced entity. - - If an entity is referenced by name (e.g. "&myEntity;" is encountered) but the lookup in the - default entity list and through the entityRef() callback fails to resolve the content, this - function is called. - - The default implementation prints a formatted message to \a stderr. - - */ - void (*unknownEntity)(const struct csxml* ctx, const char* ent); - - - - /*! \brief Callback: whitespace. - - \param ctx Parsing context. - \param ws Pointer to string of whitespace. - \returns Zero on success, non-zero on error. - - This function is called whenever a block of whitespace is encountered at stream level or - immediately after some structural element (i.e. on leading whitespace within elements). It is - generally safe to discard it, unless you need to reproduce the file verbatim. Once content is - encountered within an element, any further whitespace will be reported through the content() - callback, up to the next structural element. - - The default implementation discards the data. - - */ - int (*whiteSpace)(const struct csxml* ctx, const char* ws); - - - - /*! \brief Callback: content. - - \param ctx Parsing context. - \param content Pointer to string of cdata. - \returns Zero on success, non-zero on error. - - This function is called whenever textual content (cdata) is encountered inside an element. It - may be called multiple times simultaneously, in which case the data from each call should be - concatenated. If \a expandEntities is non-zero, then this function will also be called with the - expanded text from any entities encountered, rather than the entities themselves. - - The default implementation discards the data. - - */ - int (*content)(const struct csxml* ctx, const char* content); - - - - /*! \brief Callback: cdata block. - - \param ctx Parsing context. - \param cdata Pointer to string of cdata. - \returns Zero on success, non-zero on error. - - This function is called for all data inside a CDATA marked section. It is useful to - differentiate between cdata encoded in this manner and normal cdata if you are trying to - reproduce the orginal file verbatim. - - The default implementation calls content() with the same data. - - */ - int (*cdata)(const struct csxml* ctx, const char* cdata); - - - - /*! \brief Callback: stream restart marker. - - \param ctx Parsing context. - \param marker Pointer to marker string. - \returns Zero on success, non-zero on error. - - Whenever a stream restart marker is encountered, this function is called with the data found - inside the marker. - - The default implementation ignores the data (but note that the parser state is always reset, - regardless of what the callback does). - - */ - int (*streamRestart)(const struct csxml* ctx, const char* marker); - - - - /*! \brief Callback: processing instruction. - - \param ctx Parsing context. - \param target PI target. - \param data PI data (may be 0). - \returns Zero on success, non-zero on error. - - This callback is used to report processing instructions (PIs). If the PI has no data, then the - \a data variable can be set to 0. - - The default implementation ignores the data. - - */ - int (*PI)(const struct csxml* ctx, const char* target, const char* data); - - - - /*! \brief Callback: comment. - - \param ctx Parsing context. - \param comment Pointer to comment string data. - \returns Zero on success, non-zero on error. - - This callback is used to report comments. It is only useful if you wish to reproduce the source - file verbatim (for instance, you want to alter some data in a file but preserve user comments). - - The default implementation ignores the data. - - */ - int (*comment)(const struct csxml* ctx, const char* comment); - - - - /*! \brief Callback: element. - - \param ctx Parsing context. - \param elemName Pointer to element name string. - \param numAttrs Number of attributes. - \returns Zero on success, non-zero on error. - - This callback is used whenever an element open tag is encountered. To parse attributes, use the - numAttrs variable to determine how many there are, and then access them with: - -
        // get attribute name
-        const char* elemName = ctx->elemAttrNames.data[i].data;
-
-        // get attribute value
-        const char* elemValue = ctx->elemAttrVals.data[i].data;
- - In the case of an empty element, the closeTag() callback will be called immediately afterwards. - - The default implemenation ignores the data. - - */ - int (*element)(const struct csxml* ctx, const char* elemName, int numAttrs); - - - - /*! \brief Callback: close tag. - - \param ctx Parsing context. - \param elemName Element name. - \returns Zero on success, non-zero on error. - - This function is called whenever an element close tag is encountered. The element name will - always match the open tag element name (if not, the Streamed XML is not well formed, and an - error will be signalled before this callback is triggered). - - The default implementation ignores the data. - - */ - int (*closeTag)(const struct csxml* ctx, const char* elemName); - - - - /*! \brief Callback: entity reference. - - \param ctx Parsing context. - \param ent Entity name. - \retval 0 if the entity name does not match any known entity. - \returns Pointer to null-terminated string data for expanding entity. - - This function is called whenever \a expandEntities is true and an entity is encountered in cdata - or an attribute value. It is only called if the entity does not match one of the five built-in - defaults. You only need to provide an implementation if you know about some additional entities. - - The default implementation returns 0 ("no such entity"). - - */ - const char* (*entityRef)(const struct csxml* ctx, const char* ent); - - - - /// Internal: string buffer. - struct csxml_buf buffer; - /// Internal: string buffer. - struct csxml_buf buffer2; - /// Internal: string buffer. - struct csxml_buf elemName; - /// Internal: stack of element names, used to match open/close tags. - struct csxml_list elemStack; - /// Internal: state machine state. - int state; - /// Internal: for matching strings. - int xmlCount; - /// Internal: depth in element tree (0 = stream level). - int elementDepth; - /// Internal: for matching against restart marker string. - int restartCount; - /// Internal: for stripping windows line endings. - int skipNextNewline; - /// Internal: flag to check if we are currently parsing an attribute while expanding an entity. - int parsingAttr; - /// Internal: flag to record if current attribute was quoted with ' or " char. - int singleQuote; - /// Internal: used to expand character entities. - int entityChar; -}; - -/* 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/version b/version index 24ddb1e..a0ec19b 100644 --- a/version +++ b/version @@ -12,7 +12,7 @@ # suffixed with a string. VERMAJOR=1 VERMINOR=2 -VERMICRO=7 +VERMICRO=8 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4;