[librsvg] rsvg_xml_state_parse_from_stream(): Rename and port to Rust



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]