[librsvg/wip/rust-api: 2/5] Use libxml's structured error callback instead of vararg one



commit bf9d0616046e4dd35ddd43bb6ae7e6040f550f39
Author: Kornel LesiƄski <kornel geekhood net>
Date:   Mon Feb 18 14:03:02 2019 +0000

    Use libxml's structured error callback instead of vararg one

 librsvg/rsvg-handle.c           | 24 -----------------------
 rsvg_internals/src/lib.rs       |  2 --
 rsvg_internals/src/util.rs      |  9 +++++++++
 rsvg_internals/src/xml.rs       | 13 -------------
 rsvg_internals/src/xml2.rs      |  2 +-
 rsvg_internals/src/xml2_load.rs | 42 +++++++++++++++++++++++++++++++++--------
 6 files changed, 44 insertions(+), 48 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 65ae738a..336d522e 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -275,9 +275,6 @@ typedef struct RsvgHandleRust RsvgHandleRust;
 /* Implemented in rsvg_internals/src/xml.rs */
 typedef struct RsvgXmlState RsvgXmlState;
 
-/* Implemented in rsvg_internals/src/xml.rs */
-extern void rsvg_xml_state_error(RsvgXmlState *xml, const char *msg);
-
 G_GNUC_INTERNAL
 RsvgHandleRust *rsvg_handle_get_rust (RsvgHandle *handle);
 
@@ -1285,27 +1282,6 @@ rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
     rsvg_handle_rust_set_testing (handle, testing);
 }
 
-/* This one is defined in the C code, because the prototype has varargs
- * and we can't handle those from Rust :(
- */
-G_GNUC_INTERNAL void rsvg_sax_error_cb (void *data, const char *msg, ...);
-
-void
-rsvg_sax_error_cb (void *data, const char *msg, ...)
-{
-    RsvgXmlState *xml = data;
-    va_list args;
-    char *buf;
-
-    va_start (args, msg);
-    g_vasprintf (&buf, msg, args);
-    va_end (args);
-
-    rsvg_xml_state_error (xml, buf);
-
-    g_free (buf);
-}
-
 GType
 rsvg_error_get_type(void)
 {
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 704421af..cbdabfd1 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -88,8 +88,6 @@ pub use pixbuf_utils::{
     rsvg_rust_pixbuf_from_file_at_zoom_with_max,
 };
 
-pub use xml::rsvg_xml_state_error;
-
 #[macro_use]
 mod log;
 
diff --git a/rsvg_internals/src/util.rs b/rsvg_internals/src/util.rs
index b63387c9..17d2c2ae 100644
--- a/rsvg_internals/src/util.rs
+++ b/rsvg_internals/src/util.rs
@@ -1,5 +1,6 @@
 use libc;
 
+use std::borrow::Cow;
 use std::ffi::CStr;
 use std::str;
 
@@ -18,6 +19,14 @@ pub unsafe fn utf8_cstr<'a>(s: *const libc::c_char) -> &'a str {
     str::from_utf8_unchecked(CStr::from_ptr(s).to_bytes())
 }
 
+/// Error-tolerant C string import
+pub unsafe fn cstr<'a>(s: *const libc::c_char) -> Cow<'a, str> {
+    if s.is_null() {
+        return Cow::Borrowed("(null)");
+    }
+    CStr::from_ptr(s).to_string_lossy()
+}
+
 pub fn clamp<T: PartialOrd>(val: T, low: T, high: T) -> T {
     if val < low {
         low
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index cefd2ec8..d467efcf 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -542,19 +542,6 @@ fn parse_xml_stylesheet_processing_instruction(data: &str) -> Result<Vec<(String
     unreachable!();
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_xml_state_error(xml: *mut XmlState, msg: *const libc::c_char) {
-    assert!(!xml.is_null());
-    let xml = &mut *xml;
-
-    assert!(!msg.is_null());
-    // Unlike the functions that take UTF-8 validated strings from
-    // libxml2, I don't trust error messages to be validated.
-    let msg: String = from_glib_none(msg);
-
-    xml.error(&msg);
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/rsvg_internals/src/xml2.rs b/rsvg_internals/src/xml2.rs
index 4525fc4b..d6975683 100644
--- a/rsvg_internals/src/xml2.rs
+++ b/rsvg_internals/src/xml2.rs
@@ -107,7 +107,7 @@ pub struct xmlSAXHandler {
     pub _private: gpointer,
     pub startElementNs: gpointer,
     pub endElementNs: gpointer,
-    pub serror: gpointer,
+    pub serror: Option<unsafe extern "C" fn(user_data: *mut libc::c_void, error: xmlErrorPtr)>,
 }
 
 pub type xmlSAXHandlerPtr = *mut xmlSAXHandler;
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index d2dfb091..951d8353 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -3,6 +3,7 @@
 
 use gio;
 use gio::prelude::*;
+use std::borrow::Cow;
 use std::cell::RefCell;
 use std::mem;
 use std::ptr;
@@ -16,14 +17,11 @@ use error::LoadingError;
 use handle::LoadFlags;
 use io::get_input_stream_for_loading;
 use property_bag::PropertyBag;
+use util::cstr;
 use util::utf8_cstr;
 use xml::XmlState;
 use xml2::*;
 
-extern "C" {
-    fn rsvg_sax_error_cb(data: *mut libc::c_void);
-}
-
 fn get_xml2_sax_handler() -> xmlSAXHandler {
     let mut h: xmlSAXHandler = unsafe { mem::zeroed() };
 
@@ -36,14 +34,42 @@ fn get_xml2_sax_handler() -> xmlSAXHandler {
     h.startElement = Some(sax_start_element_cb);
     h.endElement = Some(sax_end_element_cb);
     h.processingInstruction = Some(sax_processing_instruction_cb);
-
-    // This one is defined in the C code, because the prototype has varargs
-    // and we can't handle those from Rust :(
-    h.error = rsvg_sax_error_cb as *mut _;
+    h.serror = Some(rsvg_sax_serror_cb);
 
     h
 }
 
+unsafe extern "C" fn rsvg_sax_serror_cb(user_data: *mut libc::c_void, error: xmlErrorPtr) {
+    let state = (user_data as *mut XmlState).as_mut().unwrap();
+    let error = error.as_ref().unwrap();
+
+    let level_name = match error.level {
+        1 => "warning",
+        2 => "error",
+        3 => "fatal error",
+        _ => "unknown error",
+    };
+
+    // "int2" is the column number
+    let column = if error.int2 > 0 {
+        Cow::Owned(format!(":{}", error.int2))
+    } else {
+        Cow::Borrowed("")
+    };
+
+    let full_error_message = format!(
+        "{} code={} ({}) in {}:{}{}: {}",
+        level_name,
+        error.code,
+        error.domain,
+        cstr(error.file),
+        error.line,
+        column,
+        cstr(error.message)
+    );
+    state.error(&full_error_message);
+}
+
 fn free_xml_parser_and_doc(parser: xmlParserCtxtPtr) {
     // Free the ctxt and its ctxt->myDoc - libxml2 doesn't free them together
     // http://xmlsoft.org/html/libxml-parser.html#xmlFreeParserCtxt


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]