#define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN extern "C" { #include "expat.h" }; #include "api.h" #include #include #define XML_TYPE 'XM' #pragma warning(disable: 4244) class zsRegPrimitive { public: zsRegPrimitive(const char* name, int type, void* func) { api_add_primitive(name, type, func); } }; class zsExpat { public: int depth; XML_Parser parser; 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->startfunc, u->depth); p[1] = api_create_string(u->startfunc, (char*)name); api_call_func(u->startfunc, 2, p); while (*cp) { p[0] = api_create_string(u->startfunc, (char*)(*cp++)); p[1] = api_create_string(u->startfunc, (char*)(*cp++)); api_call_func(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->endfunc, (char*)name); api_call_func(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 { void *p[1]; if (len < 32766) { char buf[32768]; memcpy(buf, s, len); buf[len] = 0; p[0] = api_create_string(u->datafunc, buf); } else { char* buf = new char[len + 1]; memcpy(buf, s, len); buf[len] = 0; p[0] = api_create_string(u->datafunc, buf); delete[] buf; } api_call_func(u->datafunc, 1, p); } } void input_error(void* caller) { api_runtime_error(caller, "bad arguments"); } void xml_destroy(void* ptr) { zsExpat *u = (zsExpat*)ptr; if (u->parser) XML_ParserFree(u->parser); delete u; } void* xml_create(void *caller, int nargs, void** args) { zsExpat *u = new zsExpat; XML_Parser parser = XML_ParserCreate(0); if (!parser) api_runtime_error(caller, "XML_ParserCreate() failed"); XML_SetUserData(parser, u); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, charData); u->parser = parser; u->depth = 0; u->startfunc = 0; u->endfunc = 0; u->datafunc = 0; return api_create_user(caller, u, 0, xml_destroy, XML_TYPE); } static zsRegPrimitive xml0("expat", 0, xml_create); void* xml_version(void *caller, int nargs, void** args) { return api_create_string(caller, (char*)XML_ExpatVersion()); } static zsRegPrimitive xml1("version",XML_TYPE, xml_version); void* xml_callback(void *caller, int nargs, void** args) { if (nargs < 4) input_error(caller); zsExpat *u = (zsExpat*)api_get_user(caller, args[0], XML_TYPE); u->startfunc = 0; u->endfunc = 0; u->datafunc = 0; const char *s; s = api_get_string(caller, args[1]); if (strlen(s) > 0) u->startfunc = api_get_func(caller, s); s = api_get_string(caller, args[2]); if (strlen(s) > 0) u->endfunc = api_get_func(caller, s); s = api_get_string(caller, args[3]); if (strlen(s) > 0) u->datafunc = api_get_func(caller, s); return 0; } static zsRegPrimitive xml2("callback", XML_TYPE, xml_callback); void* xml_parse(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); zsExpat *u = (zsExpat*)api_get_user(caller, args[0], XML_TYPE); const char* s = api_get_string(caller, args[1]); int status = XML_Parse(u->parser, s, strlen(s), 0); if (status != XML_STATUS_OK) api_runtime_error(caller, XML_ErrorString(XML_GetErrorCode(u->parser))); return 0; } static zsRegPrimitive xml3("parse", XML_TYPE, xml_parse);