#define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include "api.h" #include "buffer.h" #include #include extern "C" { #include "expat.h" }; #define XML_TYPE 'XM' #pragma warning(disable: 4244) ///////////////////////////////////////////////////////////////////// class zsExpat { public: int depth; XML_Parser parser; void *ctx; void *startfunc; void *endfunc; void *datafunc; }; void startElement(void *userData, const char *name, const char **attrs) { int k; zsExpat *u = (zsExpat*)userData; const char **cp = attrs; u->depth++; if (u->startfunc == 0) { for (k = 0; k < u->depth; ++k) putchar(' '); printf("<%s>\n", name); while (*cp) { for (k = 0; k < u->depth; ++k) putchar(' '); fprintf(stdout, "%s = %s\n", *cp++, *cp++); } fflush(stdout); } else { void *p[2]; p[0] = api_create_integer(u->ctx, u->depth); p[1] = api_create_string(u->ctx, (char*)name); api_call_func(u->ctx, u->startfunc, 2, p); while (*cp) { p[0] = api_create_string(u->ctx, (char*)(*cp++)); p[1] = api_create_string(u->ctx, (char*)(*cp++)); api_call_func(u->ctx, u->startfunc, 2, p); } } } void endElement(void *userData, const char *name) { int k; zsExpat *u = (zsExpat*)userData; if (u->endfunc == 0) { for (k = 0; k < u->depth; ++k) putchar(' '); fprintf(stdout, "\n", name); fflush(stdout); } else { void *p[1]; p[0] = api_create_string(u->ctx, (char*)name); api_call_func(u->ctx, u->endfunc, 1, p); } u->depth--; } void charData(void *userData, const char *s, int len) { int k = 0; zsExpat *u = (zsExpat*)userData; if (u->datafunc == 0) { for (k = 0; k < u->depth; ++k) putchar(' '); for (k = 0; k < len; ++k) putchar(s[k]); fprintf(stdout, "\n"); fflush(stdout); } else { zsBuffer buf(len+1); memcpy(buf.u.pchar, s, len); buf.u.pchar[len] = 0; void *p[1] = { api_create_string(u->ctx, buf.u.pchar) }; api_call_func(u->ctx, u->datafunc, 1, p); } } void xml_destroy(void* ptr) { zsExpat *u = (zsExpat*)ptr; if (u->parser) XML_ParserFree(u->parser); delete u; u = 0; } ///////////////////////////////////////////////////////////////////// void* xml_expat(void *ctx, int nargs, void** args) { zsExpat *u = new zsExpat; XML_Parser parser = XML_ParserCreate(0); if (!parser) api_runtime_error(ctx, "XML_ParserCreate() failed"); XML_SetUserData(parser, u); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, charData); u->parser = parser; u->depth = 0; u->ctx = ctx; u->startfunc = 0; u->endfunc = 0; u->datafunc = 0; return api_create_user(ctx, u, 0, xml_destroy, XML_TYPE); } void* xml_version(void *ctx, int nargs, void** args) { return api_create_string(ctx, (char*)XML_ExpatVersion()); } void* xml_callback(void *ctx, int nargs, void** args) { if (nargs < 4) api_input_error(ctx); zsExpat *u = (zsExpat*)api_get_user(ctx, args[0], XML_TYPE); u->startfunc = 0; u->endfunc = 0; u->datafunc = 0; const char *s; s = api_get_string(ctx, args[1]); if (strlen(s) > 0) u->startfunc = api_get_func(ctx, s); s = api_get_string(ctx, args[2]); if (strlen(s) > 0) u->endfunc = api_get_func(ctx, s); s = api_get_string(ctx, args[3]); if (strlen(s) > 0) u->datafunc = api_get_func(ctx, s); return 0; } void* xml_parse(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsExpat *u = (zsExpat*)api_get_user(ctx, args[0], XML_TYPE); const char* s = api_get_string(ctx, args[1]); int status = XML_Parse(u->parser, s, strlen(s), 0); if (status != XML_STATUS_OK) api_runtime_error(ctx, XML_ErrorString(XML_GetErrorCode(u->parser))); return 0; } ///////////////////////////////////////////////////////////////////// class zsRegPrimitive { public: zsRegPrimitive() { api_add_primitive("expat", 0, xml_expat); api_add_primitive("version", XML_TYPE, xml_version); api_add_primitive("callback", XML_TYPE, xml_callback); api_add_primitive("parse", XML_TYPE, xml_parse); } ~zsRegPrimitive() { } }; zsRegPrimitive xml_register;