gecko-dev/modules/xml/js/xmljs.c

170 lines
4.4 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#define XMLJS_INTERNAL
#include "xmljs.h"
#undef XMLJS_INTERNAL
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/**
* Parse a given string of XML.
* If we fail, we (try to) set an error property on the given obj, and
* return JSVAL_FALSE.
* If all is well, we return JSVAL_TRUE.
*/
JSBool
xmljs_parse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
XMLCallback *cb;
XML_Parser xml;
JSString *str;
JSBool ok;
cb = (XMLCallback *)JS_GetPrivate(cx, obj);
if (!cb) {
JS_ReportError(cx, "XMLParser object has no parser!");
return JS_FALSE;
}
if (cb->preParse &&
!cb->preParse(cx, obj, argc, argv, rval))
return JS_FALSE;
if (argc < 1) {
*rval = JSVAL_TRUE;
return JS_TRUE;
}
xml = XML_ParserCreate(NULL);
if (!xml)
return JS_FALSE; /* XXX report error */
/* after this point, have to leave via out: */
XML_SetElementHandler(xml, cb->start, cb->end);
XML_SetCharacterDataHandler(xml, cb->cdata);
XML_SetProcessingInstructionHandler(xml, cb->processing);
XML_SetUserData(xml, (void *)cb);
cb->xml = xml;
str = JS_ValueToString(cx, argv[0]);
if (!XML_Parse(xml, JS_GetStringBytes(str), JS_GetStringLength(str), 1)) {
str = JS_NewStringCopyZ(cx, XML_ErrorString(XML_GetErrorCode(xml)));
if (!str) {
ok = JS_FALSE;
goto out;
}
if (!JS_DefineProperty(cx, obj, "error", STRING_TO_JSVAL(str),
NULL, NULL, JSPROP_ENUMERATE)) {
ok = JS_FALSE;
goto out;
}
*rval = JSVAL_FALSE;
} else {
*rval = JSVAL_TRUE;
}
out:
XML_ParserFree(xml);
cb->xml = NULL;
return ok;
}
/**
* Get a file into a string and call the above.
* XXX when File object is present, we don't need this mess.
*/
static JSBool
xmljs_parseFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSString *str, *filename;
struct stat sbuf;
char * buf;
int fd, len;
*rval = JSVAL_TRUE;
if (argc < 1)
return JS_TRUE;
filename = JS_ValueToString(cx, argv[0]);
if (!filename)
return JS_TRUE;
argv[0] = STRING_TO_JSVAL(filename);
fd = open(JS_GetStringBytes(filename), O_RDONLY);
if (fd < 0) {
JS_ReportError(cx,
"XMLParser.prototype.parseFile: open of %s failed!\n",
JS_GetStringBytes(filename));
return JS_FALSE;
}
if (fstat(fd, &sbuf) < 0) {
JS_ReportError(cx,
"XMLParser.prototype.parseFile: stat of %s failed!\n",
JS_GetStringBytes(filename));
close(fd);
return JS_FALSE;
}
len = sbuf.st_size;
buf = (char *)JS_malloc(cx, len);
if (read(fd, (void *)buf, (size_t)len) < len) {
JS_ReportError(cx,
"XMLParser.prototype.parseFile: read of %s failed!\n",
JS_GetStringBytes(filename));
JS_free(cx, buf);
close(fd);
return JS_FALSE;
}
close(fd);
str = JS_NewString(cx, buf, len); /* hand buf off to engine; don't free! */
if (!str) {
JS_free(cx, buf);
return JS_FALSE;
}
argv[0] = STRING_TO_JSVAL(str);
return JS_CallFunctionName(cx, obj, "parse", argc, argv, rval);
}
JSBool
XML_Init(JSContext *cx, JSObject *obj)
{
jsval rval;
JSObject *proto;
if (!JS_EvaluateScript(cx, JS_GetGlobalObject(cx), xmljs_newObj_str,
xmljs_newObj_size,
"XMLJS internal", 0, &rval))
return JS_FALSE;
proto = JSVAL_TO_OBJECT(rval);
if (!JS_DefineFunction(cx, proto, "parse", xmljs_parse,
1, 0) ||
!JS_DefineFunction(cx, proto, "parseFile", xmljs_parseFile,
1, 0))
return JS_FALSE;
return XMLParser_Init(cx, obj, proto) && XMLGraph_Init(cx, obj, proto);
}