#include <libxml/xpathInternals.h>
-typedef struct {
- xmlDoc *doc;
- xmlParserCtxt *ctx;
-} njs_xml_doc_t;
-
-
typedef enum {
XML_NSET_TREE = 0,
XML_NSET_TREE_NO_COMMENTS,
static njs_xml_nset_t *njs_xml_nset_add(njs_xml_nset_t *nset,
njs_xml_nset_t *add);
static void njs_xml_nset_cleanup(void *data);
-static void njs_xml_error(njs_vm_t *vm, njs_xml_doc_t *tree, const char *fmt,
+static void njs_xml_error(njs_vm_t *vm, xmlParserCtxt *ctx, const char *fmt,
...);
static njs_int_t njs_xml_init(njs_vm_t *vm);
njs_xml_ext_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
+ xmlDoc *doc;
njs_int_t ret;
njs_str_t data;
- njs_xml_doc_t *tree;
+ xmlParserCtxt *ctx;
njs_mp_cleanup_t *cln;
ret = njs_vm_value_to_bytes(vm, &data, njs_arg(args, nargs, 1));
return NJS_ERROR;
}
- tree = njs_mp_zalloc(njs_vm_memory_pool(vm), sizeof(njs_xml_doc_t));
- if (njs_slow_path(tree == NULL)) {
- njs_vm_memory_error(vm);
- return NJS_ERROR;
- }
-
- tree->ctx = xmlNewParserCtxt();
- if (njs_slow_path(tree->ctx == NULL)) {
+ ctx = xmlNewParserCtxt();
+ if (njs_slow_path(ctx == NULL)) {
njs_vm_internal_error(vm, "xmlNewParserCtxt() failed");
return NJS_ERROR;
}
- tree->doc = xmlCtxtReadMemory(tree->ctx, (char *) data.start, data.length,
- NULL, NULL, XML_PARSE_NOWARNING
- | XML_PARSE_NOERROR);
- if (njs_slow_path(tree->doc == NULL)) {
- njs_xml_error(vm, tree, "failed to parse XML");
- return NJS_ERROR;
+ doc = xmlCtxtReadMemory(ctx, (char *) data.start, data.length, NULL, NULL,
+ XML_PARSE_NOWARNING | XML_PARSE_NOERROR);
+ if (njs_slow_path(doc == NULL)) {
+ njs_xml_error(vm, ctx, "failed to parse XML");
+ goto failed;
}
+ xmlFreeParserCtxt(ctx);
+
cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0);
if (njs_slow_path(cln == NULL)) {
njs_vm_memory_error(vm);
+ xmlFreeDoc(doc);
return NJS_ERROR;
}
cln->handler = njs_xml_doc_cleanup;
- cln->data = tree;
+ cln->data = doc;
+
+ return njs_vm_external_create(vm, retval, njs_xml_doc_proto_id, doc, 0);
- return njs_vm_external_create(vm, retval, njs_xml_doc_proto_id,
- tree, 0);
+failed:
+
+ xmlFreeParserCtxt(ctx);
+
+ return NJS_ERROR;
}
static njs_int_t
njs_xml_doc_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys)
{
- xmlNode *node;
- njs_int_t ret;
- njs_value_t *push;
- njs_xml_doc_t *tree;
+ xmlDoc *doc;
+ xmlNode *node;
+ njs_int_t ret;
+ njs_value_t *push;
- tree = njs_vm_external(vm, njs_xml_doc_proto_id, value);
- if (njs_slow_path(tree == NULL)) {
+ doc = njs_vm_external(vm, njs_xml_doc_proto_id, value);
+ if (njs_slow_path(doc == NULL)) {
njs_value_undefined_set(keys);
return NJS_DECLINED;
}
return NJS_ERROR;
}
- for (node = xmlDocGetRootElement(tree->doc);
+ for (node = xmlDocGetRootElement(doc);
node != NULL;
node = node->next)
{
njs_xml_doc_ext_root(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id,
njs_value_t *value, njs_value_t *unused, njs_value_t *retval)
{
- xmlNode *node;
- njs_int_t ret;
- njs_str_t name;
- njs_bool_t any;
- njs_xml_doc_t *tree;
-
- tree = njs_vm_external(vm, njs_xml_doc_proto_id, value);
- if (njs_slow_path(tree == NULL)) {
+ xmlDoc *doc;
+ xmlNode *node;
+ njs_int_t ret;
+ njs_str_t name;
+ njs_bool_t any;
+
+ doc = njs_vm_external(vm, njs_xml_doc_proto_id, value);
+ if (njs_slow_path(doc == NULL)) {
njs_value_undefined_set(retval);
return NJS_DECLINED;
}
name.start = NULL;
}
- for (node = xmlDocGetRootElement(tree->doc);
+ for (node = xmlDocGetRootElement(doc);
node != NULL;
node = node->next)
{
static xmlNode *
njs_xml_external_node(njs_vm_t *vm, njs_value_t *value)
{
- xmlNode *current;
- njs_xml_doc_t *tree;
+ xmlDoc *doc;
+ xmlNode *current;
current = njs_vm_external(vm, njs_xml_node_proto_id, value);
if (njs_slow_path(current == NULL)) {
- tree = njs_vm_external(vm, njs_xml_doc_proto_id, value);
- if (njs_slow_path(tree == NULL)) {
+ doc = njs_vm_external(vm, njs_xml_doc_proto_id, value);
+ if (njs_slow_path(doc == NULL)) {
njs_vm_type_error(vm, "\"this\" is not a XMLNode object");
return NULL;
}
- current = xmlDocGetRootElement(tree->doc);
+ current = xmlDocGetRootElement(doc);
if (njs_slow_path(current == NULL)) {
njs_vm_type_error(vm, "\"this\" is not a XMLNode object");
return NULL;
static void
njs_xml_doc_cleanup(void *data)
{
- njs_xml_doc_t *current;
-
- current = data;
-
- xmlFreeDoc(current->doc);
- xmlFreeParserCtxt(current->ctx);
+ xmlFreeDoc(data);
}
static void
-njs_xml_error(njs_vm_t *vm, njs_xml_doc_t *current, const char *fmt, ...)
+njs_xml_error(njs_vm_t *vm, xmlParserCtxt *ctx, const char *fmt, ...)
{
u_char *p, *last;
va_list args;
p = njs_vsprintf(errstr, last - 1, fmt, args);
va_end(args);
- err = xmlCtxtGetLastError(current->ctx);
+ err = xmlCtxtGetLastError(ctx);
if (err != NULL) {
p = njs_sprintf(p, last - 1, " (libxml2: \"%*s\" at %d:%d)",
typedef struct {
xmlDoc *doc;
- xmlParserCtxt *ctx;
qjs_xml_retired_t *retired;
int ref_count;
} qjs_xml_doc_t;
static void qjs_xml_list_append(xmlNode *parent, xmlNode *node);
static int qjs_xml_tree_has_namespaces(xmlNode *node);
-static void qjs_xml_error(JSContext *cx, qjs_xml_doc_t *current,
+static void qjs_xml_error(JSContext *cx, xmlParserCtxt *ctx,
const char *fmt, ...);
static JSModuleDef *qjs_xml_init(JSContext *ctx, const char *name);
{
JSValue ret;
qjs_bytes_t data;
+ xmlParserCtxt *ctx;
qjs_xml_doc_t *tree;
if (qjs_to_bytes(cx, &data, argv[0]) < 0) {
tree->ref_count = 1;
- tree->ctx = xmlNewParserCtxt();
- if (tree->ctx == NULL) {
+ ctx = xmlNewParserCtxt();
+ if (ctx == NULL) {
qjs_bytes_free(cx, &data);
JS_ThrowInternalError(cx, "xmlNewParserCtxt() failed");
qjs_xml_doc_free(JS_GetRuntime(cx), tree);
return JS_EXCEPTION;
}
- tree->doc = xmlCtxtReadMemory(tree->ctx, (char *) data.start, data.length,
- NULL, NULL, XML_PARSE_NOWARNING
- | XML_PARSE_NOERROR);
+ tree->doc = xmlCtxtReadMemory(ctx, (char *) data.start, data.length,
+ NULL, NULL, XML_PARSE_NOWARNING
+ | XML_PARSE_NOERROR);
qjs_bytes_free(cx, &data);
if (tree->doc == NULL) {
- qjs_xml_error(cx, tree, "failed to parse XML");
+ qjs_xml_error(cx, ctx, "failed to parse XML");
+ xmlFreeParserCtxt(ctx);
qjs_xml_doc_free(JS_GetRuntime(cx), tree);
return JS_EXCEPTION;
}
+ xmlFreeParserCtxt(ctx);
+
ret = JS_NewObjectClass(cx, QJS_CORE_CLASS_ID_XML_DOC);
if (JS_IsException(ret)) {
qjs_xml_doc_free(JS_GetRuntime(cx), tree);
xmlFreeDoc(current->doc);
}
- if (current->ctx != NULL) {
- xmlFreeParserCtxt(current->ctx);
- }
-
js_free_rt(rt, current);
}
static void
-qjs_xml_error(JSContext *cx, qjs_xml_doc_t *current, const char *fmt, ...)
+qjs_xml_error(JSContext *cx, xmlParserCtxt *ctx, const char *fmt, ...)
{
u_char *p, *last;
va_list args;
p = njs_vsprintf(errstr, last - 1, fmt, args);
va_end(args);
- err = xmlCtxtGetLastError(current->ctx);
+ err = xmlCtxtGetLastError(ctx);
if (err != NULL) {
p = njs_sprintf(p, last - 1, " (libxml2: \"%*s\" at %d:%d)",