Added Expat and LuaExpat, XML parsing now available in the API.
FS #336 Windows version only, Linux to be fixed soon. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1374 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user