summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/LuaExpat/lxplib.c599
-rw-r--r--source/LuaExpat/lxplib.h24
-rw-r--r--source/Plugin_NewLua.cpp7
-rw-r--r--source/XMLParser.h701
4 files changed, 1331 insertions, 0 deletions
diff --git a/source/LuaExpat/lxplib.c b/source/LuaExpat/lxplib.c
new file mode 100644
index 000000000..e26343ce9
--- /dev/null
+++ b/source/LuaExpat/lxplib.c
@@ -0,0 +1,599 @@
+/*
+** $Id: lxplib.c,v 1.16 2007/06/05 20:03:12 carregal Exp $
+** LuaExpat: Lua bind for Expat library
+** See Copyright Notice in license.html
+*/
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "expat.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+
+
+#include "lxplib.h"
+
+
+#if !defined(lua_pushliteral)
+#define lua_pushliteral(L, s) \
+ lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+#endif
+
+
+enum XPState {
+ XPSpre, /* parser just initialized */
+ XPSok, /* state while parsing */
+ XPSfinished, /* state after finished parsing */
+ XPSerror,
+ XPSstring /* state while reading a string */
+};
+
+struct lxp_userdata {
+ lua_State *L;
+ XML_Parser parser; /* associated expat parser */
+ int tableref; /* table with callbacks for this parser */
+ enum XPState state;
+ luaL_Buffer *b; /* to concatenate sequences of cdata pieces */
+};
+
+typedef struct lxp_userdata lxp_userdata;
+
+
+static int reporterror (lxp_userdata *xpu) {
+ lua_State *L = xpu->L;
+ XML_Parser p = xpu->parser;
+ lua_pushnil(L);
+ lua_pushstring(L, XML_ErrorString(XML_GetErrorCode(p)));
+ lua_pushnumber(L, XML_GetCurrentLineNumber(p));
+ lua_pushnumber(L, XML_GetCurrentColumnNumber(p) + 1);
+ lua_pushnumber(L, XML_GetCurrentByteIndex(p) + 1);
+ return 5;
+}
+
+
+static lxp_userdata *createlxp (lua_State *L) {
+ lxp_userdata *xpu = (lxp_userdata *)lua_newuserdata(L, sizeof(lxp_userdata));
+ xpu->tableref = LUA_REFNIL; /* in case of errors... */
+ xpu->parser = NULL;
+ xpu->L = NULL;
+ xpu->state = XPSpre;
+ luaL_getmetatable(L, ParserType);
+ lua_setmetatable(L, -2);
+ return xpu;
+}
+
+
+static void lxpclose (lua_State *L, lxp_userdata *xpu) {
+ luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
+ xpu->tableref = LUA_REFNIL;
+ if (xpu->parser)
+ XML_ParserFree(xpu->parser);
+ xpu->parser = NULL;
+}
+
+
+
+
+/*
+** Auxiliary function to call a Lua handle
+*/
+static void docall (lxp_userdata *xpu, int nargs, int nres) {
+ lua_State *L = xpu->L;
+ assert(xpu->state == XPSok);
+ if (lua_pcall(L, nargs + 1, nres, 0) != 0) {
+ xpu->state = XPSerror;
+ luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
+ xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX); /* error message */
+ }
+}
+
+
+/*
+** Check whether there is pending Cdata, and call its handle if necessary
+*/
+static void dischargestring (lxp_userdata *xpu) {
+ assert(xpu->state == XPSstring);
+ xpu->state = XPSok;
+ luaL_pushresult(xpu->b);
+ docall(xpu, 1, 0);
+}
+
+
+/*
+** Check whether there is a Lua handle for a given event: If so,
+** put it on the stack (to be called later), and also push `self'
+*/
+static int getHandle (lxp_userdata *xpu, const char *handle) {
+ lua_State *L = xpu->L;
+ if (xpu->state == XPSstring) dischargestring(xpu);
+ if (xpu->state == XPSerror)
+ return 0; /* some error happened before; skip all handles */
+ lua_pushstring(L, handle);
+ lua_gettable(L, 3);
+ if (lua_toboolean(L, -1) == 0) {
+ lua_pop(L, 1);
+ return 0;
+ }
+ if (!lua_isfunction(L, -1)) {
+ luaL_error(L, "lxp `%s' callback is not a function", handle);
+ }
+ lua_pushvalue(L, 1); /* first argument in every call (self) */
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** Handles
+** =======================================================
+*/
+
+
+static void f_StartCdata (void *ud) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, StartCdataKey) == 0) return; /* no handle */
+ docall(xpu, 0, 0);
+}
+
+
+static void f_EndCdataKey (void *ud) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndCdataKey) == 0) return; /* no handle */
+ docall(xpu, 0, 0);
+}
+
+
+static void f_CharData (void *ud, const char *s, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (xpu->state == XPSok) {
+ if (getHandle(xpu, CharDataKey) == 0) return; /* no handle */
+ xpu->state = XPSstring;
+ luaL_buffinit(xpu->L, xpu->b);
+ }
+ if (xpu->state == XPSstring)
+ luaL_addlstring(xpu->b, s, len);
+}
+
+
+static void f_Comment (void *ud, const char *data) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, CommentKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, data);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_Default (void *ud, const char *data, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, DefaultKey) == 0) return; /* no handle */
+ lua_pushlstring(xpu->L, data, len);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_DefaultExpand (void *ud, const char *data, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, DefaultExpandKey) == 0) return; /* no handle */
+ lua_pushlstring(xpu->L, data, len);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_StartElement (void *ud, const char *name, const char **attrs) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ int lastspec = XML_GetSpecifiedAttributeCount(xpu->parser) / 2;
+ int i = 1;
+ if (getHandle(xpu, StartElementKey) == 0) return; /* no handle */
+ lua_pushstring(L, name);
+ lua_newtable(L);
+ while (*attrs) {
+ if (i <= lastspec) {
+ lua_pushnumber(L, i++);
+ lua_pushstring(L, *attrs);
+ lua_settable(L, -3);
+ }
+ lua_pushstring(L, *attrs++);
+ lua_pushstring(L, *attrs++);
+ lua_settable(L, -3);
+ }
+ docall(xpu, 2, 0); /* call function with self, name, and attributes */
+}
+
+
+static void f_EndElement (void *ud, const char *name) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndElementKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, name);
+ docall(xpu, 1, 0);
+}
+
+
+static int f_ExternaEntity (XML_Parser p, const char *context,
+ const char *base,
+ const char *systemId,
+ const char *publicId) {
+ lxp_userdata *xpu = (lxp_userdata *)XML_GetUserData(p);
+ lua_State *L = xpu->L;
+ lxp_userdata *child;
+ int status;
+ if (getHandle(xpu, ExternalEntityKey) == 0) return 1; /* no handle */
+ child = createlxp(L);
+ child->parser = XML_ExternalEntityParserCreate(p, context, NULL);
+ if (!child->parser)
+ luaL_error(L, "XML_ParserCreate failed");
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref); */ /* child uses the same table of its father */
+ child->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ docall(xpu, 4, 1);
+ status = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ lxpclose(L, child);
+ return status;
+}
+
+
+static void f_StartNamespaceDecl (void *ud, const char *prefix,
+ const char *uri) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, StartNamespaceDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, prefix);
+ lua_pushstring(L, uri);
+ docall(xpu, 2, 0);
+}
+
+
+static void f_EndNamespaceDecl (void *ud, const char *prefix) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndNamespaceDeclKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, prefix);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_NotationDecl (void *ud, const char *notationName,
+ const char *base,
+ const char *systemId,
+ const char *publicId) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, NotationDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, notationName);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ docall(xpu, 4, 0);
+}
+
+
+static int f_NotStandalone (void *ud) {
+ int status;
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, NotStandaloneKey) == 0) return 1; /* no handle */
+ docall(xpu, 0, 1);
+ status = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return status;
+}
+
+
+static void f_ProcessingInstruction (void *ud, const char *target,
+ const char *data) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, ProcessingInstructionKey) == 0) return; /* no handle */
+ lua_pushstring(L, target);
+ lua_pushstring(L, data);
+ docall(xpu, 2, 0);
+}
+
+
+static void f_UnparsedEntityDecl (void *ud, const char *entityName,
+ const char *base,
+ const char *systemId,
+ const char *publicId,
+ const char *notationName) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, UnparsedEntityDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, entityName);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ lua_pushstring(L, notationName);
+ docall(xpu, 5, 0);
+}
+
+static void f_StartDoctypeDecl (void *ud, const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, StartDoctypeDeclKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, doctypeName);
+ lua_pushstring(xpu->L, sysid);
+ lua_pushstring(xpu->L, pubid);
+ lua_pushboolean(xpu->L, has_internal_subset);
+ docall(xpu, 4, 0);
+}
+
+/* }====================================================== */
+
+
+
+static int hasfield (lua_State *L, const char *fname) {
+ int res;
+ lua_pushstring(L, fname);
+ lua_gettable(L, 1);
+ res = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static void checkcallbacks (lua_State *L) {
+ static const char *const validkeys[] = {
+ "StartCdataSection", "EndCdataSection", "CharacterData", "Comment",
+ "Default", "DefaultExpand", "StartElement", "EndElement",
+ "ExternalEntityRef", "StartNamespaceDecl", "EndNamespaceDecl",
+ "NotationDecl", "NotStandalone", "ProcessingInstruction",
+ "UnparsedEntityDecl", "StartDoctypeDecl", NULL};
+ if (hasfield(L, "_nonstrict")) return;
+ lua_pushnil(L);
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
+ if (lua_type(L, -1) != LUA_TSTRING ||
+ luaL_findstring(lua_tostring(L, -1), validkeys) < 0)
+ luaL_error(L, "invalid key `%s' in callback table", lua_tostring(L, -1));
+#else
+ luaL_checkoption(L, -1, NULL, validkeys);
+#endif
+ }
+}
+
+
+static int lxp_make_parser (lua_State *L) {
+ XML_Parser p;
+ char sep = *luaL_optstring(L, 2, "");
+ lxp_userdata *xpu = createlxp(L);
+ p = xpu->parser = (sep == '\0') ? XML_ParserCreate(NULL) :
+ XML_ParserCreateNS(NULL, sep);
+ if (!p)
+ luaL_error(L, "XML_ParserCreate failed");
+ luaL_checktype(L, 1, LUA_TTABLE);
+ checkcallbacks(L);
+ lua_pushvalue(L, 1);
+ xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+ XML_SetUserData(p, xpu);
+ if (hasfield(L, StartCdataKey) || hasfield(L, EndCdataKey))
+ XML_SetCdataSectionHandler(p, f_StartCdata, f_EndCdataKey);
+ if (hasfield(L, CharDataKey))
+ XML_SetCharacterDataHandler(p, f_CharData);
+ if (hasfield(L, CommentKey))
+ XML_SetCommentHandler(p, f_Comment);
+ if (hasfield(L, DefaultKey))
+ XML_SetDefaultHandler(p, f_Default);
+ if (hasfield(L, DefaultExpandKey))
+ XML_SetDefaultHandlerExpand(p, f_DefaultExpand);
+ if (hasfield(L, StartElementKey) || hasfield(L, EndElementKey))
+ XML_SetElementHandler(p, f_StartElement, f_EndElement);
+ if (hasfield(L, ExternalEntityKey))
+ XML_SetExternalEntityRefHandler(p, f_ExternaEntity);
+ if (hasfield(L, StartNamespaceDeclKey) || hasfield(L, EndNamespaceDeclKey))
+ XML_SetNamespaceDeclHandler(p, f_StartNamespaceDecl, f_EndNamespaceDecl);
+ if (hasfield(L, NotationDeclKey))
+ XML_SetNotationDeclHandler(p, f_NotationDecl);
+ if (hasfield(L, NotStandaloneKey))
+ XML_SetNotStandaloneHandler(p, f_NotStandalone);
+ if (hasfield(L, ProcessingInstructionKey))
+ XML_SetProcessingInstructionHandler(p, f_ProcessingInstruction);
+ if (hasfield(L, UnparsedEntityDeclKey))
+ XML_SetUnparsedEntityDeclHandler(p, f_UnparsedEntityDecl);
+ if (hasfield(L, StartDoctypeDeclKey))
+ XML_SetStartDoctypeDeclHandler(p, f_StartDoctypeDecl);
+ return 1;
+}
+
+
+static lxp_userdata *checkparser (lua_State *L, int idx) {
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, idx, ParserType);
+ luaL_argcheck(L, xpu, idx, "expat parser expected");
+ luaL_argcheck(L, xpu->parser, idx, "parser is closed");
+ return xpu;
+}
+
+
+static int parser_gc (lua_State *L) {
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, 1, ParserType);
+ luaL_argcheck(L, xpu, 1, "expat parser expected");
+ lxpclose(L, xpu);
+ return 0;
+}
+
+
+static int setbase (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ if (XML_SetBase(xpu->parser, luaL_checkstring(L, 2)) == 0)
+ luaL_error(L, "no memory to store base");
+ return 0;
+}
+
+
+static int getbase (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_pushstring(L, XML_GetBase(xpu->parser));
+ return 1;
+}
+
+
+static int getcallbacks (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref);
+ return 1;
+}
+
+
+static int parse_aux (lua_State *L, lxp_userdata *xpu, const char *s,
+ size_t len) {
+ luaL_Buffer b;
+ int status;
+ xpu->L = L;
+ xpu->state = XPSok;
+ xpu->b = &b;
+ lua_settop(L, 2);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref);*/ /* to be used by handlers */
+ status = XML_Parse(xpu->parser, s, (int)len, s == NULL);
+ if (xpu->state == XPSstring) dischargestring(xpu);
+ if (xpu->state == XPSerror) { /* callback error? */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /* get original msg. */
+ lua_error(L);
+ }
+ if (s == NULL) xpu->state = XPSfinished;
+ if (status) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else { /* error */
+ return reporterror(xpu);
+ }
+}
+
+
+static int lxp_parse (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ size_t len;
+ const char *s = luaL_optlstring(L, 2, NULL, &len);
+ if (xpu->state == XPSfinished && s != NULL) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "cannot parse - document is finished");
+ return 2;
+ }
+ return parse_aux(L, xpu, s, len);
+}
+
+
+static int lxp_close (lua_State *L) {
+ int status = 1;
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, 1, ParserType);
+ luaL_argcheck(L, xpu, 1, "expat parser expected");
+ if (xpu->state != XPSfinished)
+ status = parse_aux(L, xpu, NULL, 0);
+ lxpclose(L, xpu);
+ if (status > 1) luaL_error(L, "error closing parser: %s",
+ lua_tostring(L, -status+1));
+ return 0;
+}
+
+
+static int lxp_pos (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ XML_Parser p = xpu->parser;
+ lua_pushnumber(L, XML_GetCurrentLineNumber(p));
+ lua_pushnumber(L, XML_GetCurrentColumnNumber(p) + 1);
+ lua_pushnumber(L, XML_GetCurrentByteIndex(p) + 1);
+ return 3;
+}
+
+
+static int lxp_setencoding (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ const char *encoding = luaL_checkstring(L, 2);
+ luaL_argcheck(L, xpu->state == XPSpre, 1, "invalid parser state");
+ XML_SetEncoding(xpu->parser, encoding);
+ return 0;
+}
+
+static int lxp_stop (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_pushboolean(L, XML_StopParser(xpu->parser, XML_FALSE) == XML_STATUS_OK);
+ return 1;
+}
+
+#if !defined LUA_VERSION_NUM
+/* Lua 5.0 */
+#define luaL_Reg luaL_reg
+#endif
+
+static const struct luaL_Reg lxp_meths[] = {
+ {"parse", lxp_parse},
+ {"close", lxp_close},
+ {"__gc", parser_gc},
+ {"pos", lxp_pos},
+ {"setencoding", lxp_setencoding},
+ {"getcallbacks", getcallbacks},
+ {"getbase", getbase},
+ {"setbase", setbase},
+ {"stop", lxp_stop},
+ {NULL, NULL}
+};
+
+static const struct luaL_Reg lxp_funcs[] = {
+ {"new", lxp_make_parser},
+ {NULL, NULL}
+};
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (lua_State *L) {
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, "LuaExpat is a SAX XML parser based on the Expat library");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, "LuaExpat 1.3.0");
+ lua_settable (L, -3);
+}
+
+
+#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
+/*
+** Adapted from Lua 5.2.0
+*/
+static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ luaL_checkstack(L, nup, "too many upvalues");
+ for (; l->name != NULL; l++) { /* fill the table with given functions */
+ int i;
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushstring(L, l->name);
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_settable(L, -(nup + 3));
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+#endif
+
+
+int luaopen_lxp (lua_State *L) {
+ luaL_newmetatable(L, ParserType);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -3);
+
+ luaL_setfuncs (L, lxp_meths, 0);
+ lua_pop (L, 1); /* remove metatable */
+
+ // _X 2013_04_09: Modified to allow embedding
+ luaL_openlib (L, "lxp", lxp_funcs, 0);
+ /*
+ lua_newtable (L);
+ luaL_setfuncs (L, lxp_funcs, 0);
+ */
+ set_info (L);
+ return 1;
+}
diff --git a/source/LuaExpat/lxplib.h b/source/LuaExpat/lxplib.h
new file mode 100644
index 000000000..9c0be4f78
--- /dev/null
+++ b/source/LuaExpat/lxplib.h
@@ -0,0 +1,24 @@
+/*
+** See Copyright Notice in license.html
+*/
+
+#define ParserType "Expat"
+
+#define StartCdataKey "StartCdataSection"
+#define EndCdataKey "EndCdataSection"
+#define CharDataKey "CharacterData"
+#define CommentKey "Comment"
+#define DefaultKey "Default"
+#define DefaultExpandKey "DefaultExpand"
+#define StartElementKey "StartElement"
+#define EndElementKey "EndElement"
+#define ExternalEntityKey "ExternalEntityRef"
+#define StartNamespaceDeclKey "StartNamespaceDecl"
+#define EndNamespaceDeclKey "EndNamespaceDecl"
+#define NotationDeclKey "NotationDecl"
+#define NotStandaloneKey "NotStandalone"
+#define ProcessingInstructionKey "ProcessingInstruction"
+#define UnparsedEntityDeclKey "UnparsedEntityDecl"
+#define StartDoctypeDeclKey "StartDoctypeDecl"
+
+int luaopen_lxp (lua_State *L);
diff --git a/source/Plugin_NewLua.cpp b/source/Plugin_NewLua.cpp
index dc3f62c6b..01e9b0cdb 100644
--- a/source/Plugin_NewLua.cpp
+++ b/source/Plugin_NewLua.cpp
@@ -24,6 +24,12 @@ extern "C"
LUALIB_API int luaopen_lsqlite3(lua_State * L);
}
+// fwd: LuaExpat/lxplib.c:
+extern "C"
+{
+ int luaopen_lxp(lua_State * L);
+}
+
@@ -84,6 +90,7 @@ bool cPlugin_NewLua::Initialize(void)
tolua_AllToLua_open(m_LuaState);
ManualBindings::Bind(m_LuaState);
luaopen_lsqlite3(m_LuaState);
+ luaopen_lxp(m_LuaState);
// Inject the identification global variables into the state:
lua_pushlightuserdata(m_LuaState, this);
diff --git a/source/XMLParser.h b/source/XMLParser.h
new file mode 100644
index 000000000..a6b571862
--- /dev/null
+++ b/source/XMLParser.h
@@ -0,0 +1,701 @@
+
+// XMLParser.h
+
+// Interfaces to the CXMLParser class representing the base class for XML parsing
+
+// To use, derive a class from this base and override its OnStartElement(), OnEndElement() and OnCharacters() functions
+
+
+
+
+
+#pragma once
+
+#include "expat/expat.h"
+
+
+
+
+
+class CXMLParser
+{
+public:
+ CXMLParser(void);
+ virtual ~CXMLParser();
+
+ // The actual parsing, may be called several times; the last time needs iIsFinal == true (-> flush)
+ int Parse(const char * iData, size_t iLength, bool iIsFinal = false);
+
+private:
+ // LibExpat stuff:
+ XML_Parser mParser;
+
+ static void StartElementHandler(void * iContext, const XML_Char * iElement, const XML_Char ** iAttributes)
+ {
+ ((CXMLParser *)iContext)->OnStartElement(iElement, iAttributes);
+ }
+
+ static void EndElementHandler (void * iContext, const XML_Char * iElement)
+ {
+ ((CXMLParser *)iContext)->OnEndElement(iElement);
+ }
+
+ static void CharacterDataHandler (void * iContext, const XML_Char * iData, int iLength)
+ {
+ ((CXMLParser *)iContext)->OnCharacters(iData, iLength);
+ }
+
+protected:
+ virtual void OnStartElement(const XML_Char * iElement, const XML_Char ** iAttributes) = 0;
+ virtual void OnEndElement (const XML_Char * iElement) = 0;
+ virtual void OnCharacters (const XML_Char * iCharacters, int iLength) = 0;
+} ;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// The following template has been modified from code available at
+// http://www.codeproject.com/Articles/1847/C-Wrappers-for-the-Expat-XML-Parser
+// It uses templates to remove the virtual function call penalty (both size and speed) for each callback
+
+/* Usage:
+1, Declare a subclass:
+ class CMyParser : public CExpatImpl<CMyParser>
+2, Declare handlers that you want in that subclass:
+ void CMyParser::OnEndElement(const XML_Char * iTagName);
+3, Create an instance of your class:
+ CMyParser Parser;
+4, Call Create():
+ Parser.Create(NULL, NULL);
+4, Call Parse(), repeatedly:
+ Parser.Parse(Buffer, Length);
+*/
+
+template <class _T>
+class CExpatImpl
+{
+
+// @access Constructors and destructors
+public:
+
+ // @cmember General constructor
+
+ CExpatImpl ()
+ {
+ m_p = NULL;
+ }
+
+ // @cmember Destructor
+
+ ~CExpatImpl ()
+ {
+ Destroy ();
+ }
+
+// @access Parser creation and deletion methods
+public:
+
+ // @cmember Create a parser
+
+ bool Create (const XML_Char * pszEncoding = NULL, const XML_Char * pszSep = NULL)
+ {
+ // Destroy the old parser
+ Destroy ();
+
+ // If the encoding or seperator are empty, then NULL
+ if (pszEncoding != NULL && pszEncoding [0] == 0)
+ {
+ pszEncoding = NULL;
+ }
+ if (pszSep != NULL && pszSep [0] == 0)
+ {
+ pszSep = NULL;
+ }
+
+ // Create the new parser
+ m_p = XML_ParserCreate_MM (pszEncoding, NULL, pszSep);
+ if (m_p == NULL)
+ {
+ return false;
+ }
+
+ // Invoke the post create routine
+ _T * pThis = static_cast <_T *> (this);
+ pThis ->OnPostCreate ();
+
+ // Set the user data used in callbacks
+ XML_SetUserData (m_p, (void *) this);
+ return true;
+ }
+
+ // @cmember Destroy the parser
+
+ void Destroy (void)
+ {
+ if (m_p != NULL)
+ {
+ XML_ParserFree (m_p);
+ }
+ m_p = NULL;
+ }
+
+
+ // @cmember Parse a block of data
+
+ bool Parse (const char *pszBuffer, int nLength, bool fIsFinal = true)
+ {
+ assert (m_p != NULL);
+ return XML_Parse (m_p, pszBuffer, nLength, fIsFinal) != 0;
+ }
+
+ // @cmember Parse internal buffer
+
+ bool ParseBuffer (int nLength, bool fIsFinal = true)
+ {
+ assert (m_p != NULL);
+ return XML_ParseBuffer (m_p, nLength, fIsFinal) != 0;
+ }
+
+ // @cmember Get the internal buffer
+
+ void *GetBuffer (int nLength)
+ {
+ assert (m_p != NULL);
+ return XML_GetBuffer (m_p, nLength);
+ }
+
+
+protected:
+ // Parser callback enable/disable methods:
+
+ // @cmember Enable/Disable the start element handler
+
+ void EnableStartElementHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetStartElementHandler (m_p, fEnable ? StartElementHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the end element handler
+
+ void EnableEndElementHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetEndElementHandler (m_p, fEnable ? EndElementHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the element handlers
+
+ void EnableElementHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ EnableStartElementHandler (fEnable);
+ EnableEndElementHandler (fEnable);
+ }
+
+ // @cmember Enable/Disable the character data handler
+
+ void EnableCharacterDataHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetCharacterDataHandler (m_p, fEnable ? CharacterDataHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the processing instruction handler
+
+ void EnableProcessingInstructionHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetProcessingInstructionHandler (m_p, fEnable ? ProcessingInstructionHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the comment handler
+
+ void EnableCommentHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetCommentHandler (m_p, fEnable ? CommentHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the start CDATA section handler
+
+ void EnableStartCdataSectionHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetStartCdataSectionHandler (m_p, fEnable ? StartCdataSectionHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the end CDATA section handler
+
+ void EnableEndCdataSectionHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetEndCdataSectionHandler (m_p, fEnable ? EndCdataSectionHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the CDATA section handlers
+
+ void EnableCdataSectionHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ EnableStartCdataSectionHandler (fEnable);
+ EnableEndCdataSectionHandler (fEnable);
+ }
+
+ // @cmember Enable/Disable default handler
+
+ void EnableDefaultHandler (bool fEnable = true, bool fExpand = true)
+ {
+ assert (m_p != NULL);
+ if (fExpand)
+ {
+ XML_SetDefaultHandlerExpand (m_p, fEnable ? DefaultHandler : NULL);
+ }
+ else
+ XML_SetDefaultHandler (m_p, fEnable ? DefaultHandler : NULL);
+ }
+
+ // @cmember Enable/Disable external entity ref handler
+
+ void EnableExternalEntityRefHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetExternalEntityRefHandler (m_p, fEnable ? ExternalEntityRefHandler : NULL);
+ }
+
+ // @cmember Enable/Disable unknown encoding handler
+
+ void EnableUnknownEncodingHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetUnknownEncodingHandler (m_p, fEnable ? UnknownEncodingHandler : NULL);
+ }
+
+ // @cmember Enable/Disable start namespace handler
+
+ void EnableStartNamespaceDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetStartNamespaceDeclHandler (m_p, fEnable ? StartNamespaceDeclHandler : NULL);
+ }
+
+ // @cmember Enable/Disable end namespace handler
+
+ void EnableEndNamespaceDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetEndNamespaceDeclHandler (m_p, fEnable ? EndNamespaceDeclHandler : NULL);
+ }
+
+ // @cmember Enable/Disable namespace handlers
+
+ void EnableNamespaceDeclHandler (bool fEnable = true)
+ {
+ EnableStartNamespaceDeclHandler (fEnable);
+ EnableEndNamespaceDeclHandler (fEnable);
+ }
+
+ // @cmember Enable/Disable the XML declaration handler
+
+ void EnableXmlDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetXmlDeclHandler (m_p, fEnable ? XmlDeclHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the start DOCTYPE declaration handler
+
+ void EnableStartDoctypeDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetStartDoctypeDeclHandler (m_p, fEnable ? StartDoctypeDeclHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the end DOCTYPE declaration handler
+
+ void EnableEndDoctypeDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ XML_SetEndDoctypeDeclHandler (m_p,
+ fEnable ? EndDoctypeDeclHandler : NULL);
+ }
+
+ // @cmember Enable/Disable the DOCTYPE declaration handler
+
+ void EnableDoctypeDeclHandler (bool fEnable = true)
+ {
+ assert (m_p != NULL);
+ EnableStartDoctypeDeclHandler (fEnable);
+ EnableEndDoctypeDeclHandler (fEnable);
+ }
+
+public:
+ // Parser error reporting methods
+
+ // @cmember Get last error
+
+ enum XML_Error GetErrorCode ()
+ {
+ assert (m_p != NULL);
+ return XML_GetErrorCode (m_p);
+ }
+
+ // @cmember Get the current byte index
+
+ long GetCurrentByteIndex ()
+ {
+ assert (m_p != NULL);
+ return XML_GetCurrentByteIndex (m_p);
+ }
+
+ // @cmember Get the current line number
+
+ int GetCurrentLineNumber ()
+ {
+ assert (m_p != NULL);
+ return XML_GetCurrentLineNumber (m_p);
+ }
+
+ // @cmember Get the current column number
+
+ int GetCurrentColumnNumber ()
+ {
+ assert (m_p != NULL);
+ return XML_GetCurrentColumnNumber (m_p);
+ }
+
+ // @cmember Get the current byte count
+
+ int GetCurrentByteCount ()
+ {
+ assert (m_p != NULL);
+ return XML_GetCurrentByteCount (m_p);
+ }
+
+ // @cmember Get the input context
+
+ const char *GetInputContext (int *pnOffset, int *pnSize)
+ {
+ assert (m_p != NULL);
+ return XML_GetInputContext (m_p, pnOffset, pnSize);
+ }
+
+ // @cmember Get last error string
+
+ const XML_LChar *GetErrorString ()
+ {
+ return XML_ErrorString (GetErrorCode ());
+ }
+
+ // @cmember Return the version string
+
+ static const XML_LChar *GetExpatVersion ()
+ {
+ return XML_ExpatVersion ();
+ }
+
+ // @cmember Get the version information
+
+ static void GetExpatVersion (int *pnMajor, int *pnMinor, int *pnMicro)
+ {
+ XML_expat_version v = XML_ExpatVersionInfo ();
+ if (pnMajor)
+ *pnMajor = v .major;
+ if (pnMinor)
+ *pnMinor = v .minor;
+ if (pnMicro)
+ *pnMicro = v .micro;
+ }
+
+ // @cmember Get last error string
+
+ static const XML_LChar *GetErrorString (enum XML_Error nError)
+ {
+ return XML_ErrorString (nError);
+ }
+
+
+ // Public handler methods:
+ // The template parameter should provide their own implementation for those handlers that they want
+
+ // @cmember Start element handler
+
+ void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs)
+ {
+ return;
+ }
+
+ // @cmember End element handler
+
+ void OnEndElement (const XML_Char *pszName)
+ {
+ return;
+ }
+
+ // @cmember Character data handler
+
+ void OnCharacterData (const XML_Char *pszData, int nLength)
+ {
+ return;
+ }
+
+ // @cmember Processing instruction handler
+
+ void OnProcessingInstruction (const XML_Char *pszTarget,
+ const XML_Char *pszData)
+ {
+ return;
+ }
+
+ // @cmember Comment handler
+
+ void OnComment (const XML_Char *pszData)
+ {
+ return;
+ }
+
+ // @cmember Start CDATA section handler
+
+ void OnStartCdataSection ()
+ {
+ return;
+ }
+
+ // @cmember End CDATA section handler
+
+ void OnEndCdataSection ()
+ {
+ return;
+ }
+
+ // @cmember Default handler
+
+ void OnDefault (const XML_Char *pszData, int nLength)
+ {
+ return;
+ }
+
+ // @cmember External entity ref handler
+
+ bool OnExternalEntityRef (const XML_Char *pszContext,
+ const XML_Char *pszBase, const XML_Char *pszSystemID,
+ const XML_Char *pszPublicID)
+ {
+ return false;
+ }
+
+ // @cmember Unknown encoding handler
+
+ bool OnUnknownEncoding (const XML_Char *pszName, XML_Encoding *pInfo)
+ {
+ return false;
+ }
+
+ // @cmember Start namespace declaration handler
+
+ void OnStartNamespaceDecl (const XML_Char *pszPrefix,
+ const XML_Char *pszURI)
+ {
+ return;
+ }
+
+ // @cmember End namespace declaration handler
+
+ void OnEndNamespaceDecl (const XML_Char *pszPrefix)
+ {
+ return;
+ }
+
+ // @cmember XML declaration handler
+
+ void OnXmlDecl (const XML_Char *pszVersion, const XML_Char *pszEncoding,
+ bool fStandalone)
+ {
+ return;
+ }
+
+ // @cmember Start DOCTYPE declaration handler
+
+ void OnStartDoctypeDecl (const XML_Char *pszDoctypeName,
+ const XML_Char *pszSysID, const XML_Char *pszPubID,
+ bool fHasInternalSubset)
+ {
+ return;
+ }
+
+ // @cmember End DOCTYPE declaration handler
+
+ void OnEndDoctypeDecl ()
+ {
+ return;
+ }
+
+// @access Protected methods
+protected:
+
+ // @cmember Handle any post creation
+
+ void OnPostCreate ()
+ {
+ }
+
+// @access Protected static methods
+protected:
+
+ // @cmember Start element handler wrapper
+
+ static void __cdecl StartElementHandler (void *pUserData,
+ const XML_Char *pszName, const XML_Char **papszAttrs)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnStartElement (pszName, papszAttrs);
+ }
+
+ // @cmember End element handler wrapper
+
+ static void __cdecl EndElementHandler (void *pUserData,
+ const XML_Char *pszName)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnEndElement (pszName);
+ }
+
+ // @cmember Character data handler wrapper
+
+ static void __cdecl CharacterDataHandler (void *pUserData,
+ const XML_Char *pszData, int nLength)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnCharacterData (pszData, nLength);
+ }
+
+ // @cmember Processing instruction handler wrapper
+
+ static void __cdecl ProcessingInstructionHandler (void *pUserData,
+ const XML_Char *pszTarget, const XML_Char *pszData)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnProcessingInstruction (pszTarget, pszData);
+ }
+
+ // @cmember Comment handler wrapper
+
+ static void __cdecl CommentHandler (void *pUserData,
+ const XML_Char *pszData)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnComment (pszData);
+ }
+
+ // @cmember Start CDATA section wrapper
+
+ static void __cdecl StartCdataSectionHandler (void *pUserData)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnStartCdataSection ();
+ }
+
+ // @cmember End CDATA section wrapper
+
+ static void __cdecl EndCdataSectionHandler (void *pUserData)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnEndCdataSection ();
+ }
+
+ // @cmember Default wrapper
+
+ static void __cdecl DefaultHandler (void *pUserData,
+ const XML_Char *pszData, int nLength)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnDefault (pszData, nLength);
+ }
+
+ // @cmember External entity ref wrapper
+
+ static int __cdecl ExternalEntityRefHandler (void *pUserData,
+ const XML_Char *pszContext, const XML_Char *pszBase,
+ const XML_Char *pszSystemID, const XML_Char *pszPublicID)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ return pThis ->OnExternalEntityRef (pszContext,
+ pszBase, pszSystemID, pszPublicID) ? 1 : 0;
+ }
+
+ // @cmember Unknown encoding wrapper
+
+ static int __cdecl UnknownEncodingHandler (void * pUserData, const XML_Char * pszName, XML_Encoding * pInfo)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ return pThis ->OnUnknownEncoding (pszName, pInfo) ? 1 : 0;
+ }
+
+ // @cmember Start namespace decl wrapper
+
+ static void __cdecl StartNamespaceDeclHandler (void * pUserData, const XML_Char * pszPrefix, const XML_Char * pszURI)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnStartNamespaceDecl (pszPrefix, pszURI);
+ }
+
+ // @cmember End namespace decl wrapper
+
+ static void __cdecl EndNamespaceDeclHandler (void * pUserData, const XML_Char * pszPrefix)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnEndNamespaceDecl (pszPrefix);
+ }
+
+ // @cmember XML declaration wrapper
+
+ static void __cdecl XmlDeclHandler (void *pUserData, const XML_Char *pszVersion, const XML_Char *pszEncoding, int nStandalone)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnXmlDecl (pszVersion, pszEncoding, nStandalone != 0);
+ }
+
+ // @cmember Start Doctype declaration wrapper
+
+ static void __cdecl StartDoctypeDeclHandler (
+ void *pUserData, const XML_Char *pszDoctypeName, const XML_Char *pszSysID,
+ const XML_Char *pszPubID, int nHasInternalSubset
+ )
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnStartDoctypeDecl (pszDoctypeName, pszSysID,
+ pszPubID, nHasInternalSubset != 0);
+ }
+
+ // @cmember End Doctype declaration wrapper
+
+ static void __cdecl EndDoctypeDeclHandler (void *pUserData)
+ {
+ _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+ pThis ->OnEndDoctypeDecl ();
+ }
+
+
+protected:
+
+ XML_Parser m_p;
+
+ /// Returns the value of the specified attribute, if found; NULL otherwise
+ static const XML_Char * FindAttr(const XML_Char ** iAttrs, const XML_Char * iAttrToFind)
+ {
+ for (const XML_Char ** Attr = iAttrs; *Attr != NULL; Attr += 2)
+ {
+ if (strcmp(*Attr, iAttrToFind) == 0)
+ {
+ return *(Attr + 1);
+ }
+ } // for Attr - iAttrs[]
+ return NULL;
+ }
+} ;
+
+
+
+