[librsvg] rsvg_xml_state_parse_from_stream(): Rename and port to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] rsvg_xml_state_parse_from_stream(): Rename and port to Rust
- Date: Thu, 6 Dec 2018 00:13:08 +0000 (UTC)
commit 29d064f382a97e202df8f0a030b9f844035f70a4
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Dec 5 18:11:38 2018 -0600
rsvg_xml_state_parse_from_stream(): Rename and port to Rust
librsvg/rsvg-load.c | 94 ++++++-------------------
rsvg_internals/src/lib.rs | 2 +-
rsvg_internals/src/xml2_load.rs | 149 ++++++++++++++++++++++++++++++++--------
3 files changed, 143 insertions(+), 102 deletions(-)
---
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 5c909f3c..dcbd147d 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -47,19 +47,22 @@ extern void rsvg_xml_state_free (RsvgXmlState *xml);
extern gboolean rsvg_xml_state_tree_is_valid(RsvgXmlState *xml, GError **error);
extern void rsvg_xml_state_error(RsvgXmlState *xml, const char *msg);
+/* Implemented in rsvg_internals/src/xml2_load.rs */
+extern gboolean rsvg_xml_state_parse_from_stream (RsvgXmlState *xml,
+ gboolean unlimited_size,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
/* Implemented in rsvg_internals/src/handle.rs */
extern void rsvg_handle_rust_steal_result (RsvgHandleRust *raw_handle, RsvgXmlState *xml);
/* Implemented in rsvg_internals/src/xml2_load.rs */
-extern xmlParserCtxtPtr rsvg_create_xml_stream_parser (RsvgXmlState *xml,
- gboolean unlimited_size,
- GInputStream *stream,
- GCancellable *cancellable,
- GError **error);
extern xmlParserCtxtPtr rsvg_create_xml_push_parser (RsvgXmlState *xml,
gboolean unlimited_size,
const char *base_uri,
GError **error);
+extern void rsvg_set_error_from_xml (GError **error, xmlParserCtxtPtr ctxt);
/* Holds the XML parsing state */
@@ -142,63 +145,6 @@ rsvg_load_finish_load (RsvgLoad *load, GError **error)
return was_successful;
}
-static void
-set_error_from_xml (GError **error, xmlParserCtxtPtr ctxt)
-{
- xmlErrorPtr xerr;
-
- xerr = xmlCtxtGetLastError (ctxt);
- if (xerr) {
- g_set_error (error, rsvg_error_quark (), 0,
- _("Error domain %d code %d on line %d column %d of %s: %s"),
- xerr->domain, xerr->code,
- xerr->line, xerr->int2,
- xerr->file ? xerr->file : "data",
- xerr->message ? xerr->message: "-");
- } else {
- g_set_error (error, rsvg_error_quark (), 0, _("Error parsing XML data"));
- }
-}
-
-static gboolean
-rsvg_parse_xml_from_stream (RsvgXmlState *xml,
- gboolean unlimited_size,
- GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- GError *err = NULL;
- xmlParserCtxtPtr xml_parser;
- gboolean xml_parse_success;
- gboolean svg_parse_success;
-
- xml_parser = rsvg_create_xml_stream_parser (xml,
- unlimited_size,
- stream,
- cancellable,
- &err);
- if (!xml_parser) {
- g_assert (err != NULL);
- g_propagate_error (error, err);
- return FALSE;
- }
-
- g_assert (err == NULL);
- xml_parse_success = xmlParseDocument (xml_parser) == 0;
-
- svg_parse_success = err == NULL;
-
- if (!svg_parse_success) {
- g_propagate_error (error, err);
- } else if (!xml_parse_success) {
- set_error_from_xml (error, xml_parser);
- }
-
- xml_parser = free_xml_parser_and_doc (xml_parser);
-
- return svg_parse_success && xml_parse_success;
-}
-
gboolean
rsvg_load_handle_xml_xinclude (RsvgHandle *handle, const char *href)
{
@@ -211,11 +157,11 @@ rsvg_load_handle_xml_xinclude (RsvgHandle *handle, const char *href)
if (stream) {
gboolean success;
- success = rsvg_parse_xml_from_stream (handle->priv->load->xml.rust_state,
- handle->priv->load->unlimited_size,
- stream,
- handle->priv->cancellable,
- NULL);
+ success = rsvg_xml_state_parse_from_stream (handle->priv->load->xml.rust_state,
+ handle->priv->load->unlimited_size,
+ stream,
+ handle->priv->cancellable,
+ NULL);
g_object_unref (stream);
@@ -264,7 +210,7 @@ write_impl (RsvgLoad *load, const guchar * buf, gsize count, GError **error)
if (load->xml.ctxt != NULL) {
result = xmlParseChunk (load->xml.ctxt, (char *) buf, count, 0);
if (result != 0) {
- set_error_from_xml (error, load->xml.ctxt);
+ rsvg_set_error_from_xml (error, load->xml.ctxt);
return FALSE;
}
} else {
@@ -289,7 +235,7 @@ close_impl (RsvgLoad *load, GError ** error)
result = xmlParseChunk (load->xml.ctxt, "", 0, TRUE);
if (result != 0) {
- set_error_from_xml (error, load->xml.ctxt);
+ rsvg_set_error_from_xml (error, load->xml.ctxt);
load->xml.ctxt = free_xml_parser_and_doc (load->xml.ctxt);
return FALSE;
}
@@ -331,11 +277,11 @@ rsvg_load_read_stream_sync (RsvgLoad *load,
g_assert (load->xml.ctxt == NULL);
- res = rsvg_parse_xml_from_stream (load->xml.rust_state,
- load->unlimited_size,
- stream,
- cancellable,
- &err);
+ res = rsvg_xml_state_parse_from_stream (load->xml.rust_state,
+ load->unlimited_size,
+ stream,
+ cancellable,
+ &err);
if (!res) {
g_propagate_error (error, err);
}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index a4e166a8..899827b5 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -70,7 +70,7 @@ pub use xml::{
rsvg_xml_state_tree_is_valid,
};
-pub use xml2_load::{rsvg_create_xml_push_parser, rsvg_create_xml_stream_parser};
+pub use xml2_load::{rsvg_create_xml_push_parser, rsvg_xml_state_parse_from_stream};
#[macro_use]
mod log;
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index abf6ca77..4160291b 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -12,7 +12,7 @@ use std::str;
use glib::translate::*;
-use error::set_gerror;
+use error::{set_gerror, RsvgError};
use property_bag::PropertyBag;
use util::utf8_cstr;
use xml::{RsvgXmlState, XmlState};
@@ -42,6 +42,21 @@ fn get_xml2_sax_handler() -> xmlSAXHandler {
h
}
+fn free_xml_parser_and_doc(parser: xmlParserCtxtPtr) {
+ unsafe {
+ if !parser.is_null() {
+ let rparser = &mut *parser;
+
+ if !rparser.myDoc.is_null() {
+ xmlFreeDoc(rparser.myDoc);
+ rparser.myDoc = ptr::null_mut();
+ }
+
+ xmlFreeParserCtxt(parser);
+ }
+ }
+}
+
unsafe extern "C" fn sax_get_entity_cb(
ctx: *mut libc::c_void,
name: *const libc::c_char,
@@ -241,40 +256,40 @@ unsafe extern "C" fn stream_ctx_close(context: *mut libc::c_void) -> libc::c_int
ret
}
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_create_xml_stream_parser(
- xml: *mut RsvgXmlState,
- unlimited_size: glib_sys::gboolean,
- stream: *mut gio_sys::GInputStream,
- cancellable: *mut gio_sys::GCancellable,
+fn create_xml_stream_parser(
+ xml: &mut XmlState,
+ unlimited_size: bool,
+ stream: gio::InputStream,
+ cancellable: Option<gio::Cancellable>,
error: *mut *mut glib_sys::GError,
-) -> xmlParserCtxtPtr {
+) -> Result<xmlParserCtxtPtr, glib::Error> {
let ctx = Box::new(StreamCtx {
- stream: from_glib_none(stream),
- cancellable: from_glib_none(cancellable),
+ stream,
+ cancellable,
error,
});
let mut sax_handler = get_xml2_sax_handler();
- let parser = xmlCreateIOParserCtxt(
- &mut sax_handler,
- xml as *mut _,
- Some(stream_ctx_read),
- Some(stream_ctx_close),
- Box::into_raw(ctx) as *mut _,
- XML_CHAR_ENCODING_NONE,
- );
-
- if parser.is_null() {
- set_gerror(error, 0, "Error creating XML parser");
- // on error, xmlCreateIOParserCtxt() frees our context via the
- // stream_ctx_close function
- } else {
- set_xml_parse_options(parser, from_glib(unlimited_size));
+ unsafe {
+ let parser = xmlCreateIOParserCtxt(
+ &mut sax_handler,
+ xml as *mut _ as *mut _,
+ Some(stream_ctx_read),
+ Some(stream_ctx_close),
+ Box::into_raw(ctx) as *mut _,
+ XML_CHAR_ENCODING_NONE,
+ );
+
+ if parser.is_null() {
+ // on error, xmlCreateIOParserCtxt() frees our context via the
+ // stream_ctx_close function
+ Err(glib::Error::new(RsvgError, "Error creating XML parser"))
+ } else {
+ set_xml_parse_options(parser, unlimited_size);
+ Ok(parser)
+ }
}
-
- parser
}
#[no_mangle]
@@ -296,3 +311,83 @@ pub unsafe extern "C" fn rsvg_create_xml_push_parser(
parser
}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_set_error_from_xml(
+ error: *mut *mut glib_sys::GError,
+ ctxt: xmlParserCtxtPtr,
+) {
+ let xerr = xmlCtxtGetLastError(ctxt as *mut _);
+
+ if !xerr.is_null() {
+ let xerr = &*xerr;
+
+ let file = if xerr.file.is_null() {
+ "data".to_string()
+ } else {
+ from_glib_none(xerr.file)
+ };
+
+ let message = if xerr.message.is_null() {
+ "-".to_string()
+ } else {
+ from_glib_none(xerr.message)
+ };
+
+ let msg = format!(
+ "Error domain {} code {} on line {} column {} of {}: {}",
+ xerr.domain, xerr.code, xerr.line, xerr.int2, file, message
+ );
+
+ set_gerror(error, 0, &msg);
+ } else {
+ set_gerror(error, 0, "Error parsing XML data");
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_xml_state_parse_from_stream(
+ xml: *mut RsvgXmlState,
+ unlimited_size: glib_sys::gboolean,
+ stream: *mut gio_sys::GInputStream,
+ cancellable: *mut gio_sys::GCancellable,
+ error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+ assert!(!xml.is_null());
+ let xml = &mut *(xml as *mut XmlState);
+
+ let unlimited_size = from_glib(unlimited_size);
+
+ let stream = from_glib_none(stream);
+ let cancellable = from_glib_none(cancellable);
+
+ let mut err: *mut glib_sys::GError = ptr::null_mut();
+
+ match create_xml_stream_parser(xml, unlimited_size, stream, cancellable, &mut err) {
+ Ok(parser) => {
+ let xml_parse_success = xmlParseDocument(parser) == 0;
+
+ let svg_parse_success = err.is_null();
+
+ if !svg_parse_success {
+ if !error.is_null() {
+ *error = err;
+ }
+ } else if !xml_parse_success {
+ rsvg_set_error_from_xml(error, parser);
+ }
+
+ free_xml_parser_and_doc(parser);
+
+ (svg_parse_success && xml_parse_success).to_glib()
+ }
+
+ Err(e) => {
+ if !error.is_null() {
+ *error = e.to_glib_full() as *mut _;
+ }
+
+ false.to_glib()
+ }
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]