[librsvg/wip/subclass] Use libxml's structured error callback instead of vararg one



commit c8dafbf705a5641f6c3cf043a356c787d85a0cd5
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 | 34 ++++++++++++++++++++++++++--------
 6 files changed, 36 insertions(+), 48 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index d0e60857..7a1ee909 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -131,9 +131,6 @@
 /* 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);
-
 /* Implemented in rsvg_internals/src/handle.rs */
 extern double rsvg_handle_rust_get_dpi_x (RsvgHandle *raw_handle);
 extern double rsvg_handle_rust_get_dpi_y (RsvgHandle *raw_handle);
@@ -874,27 +871,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 b064a65e..091074f9 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -89,8 +89,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 3a7c7cac..28c7913d 100644
--- a/rsvg_internals/src/util.rs
+++ b/rsvg_internals/src/util.rs
@@ -1,6 +1,7 @@
 use libc;
 
 use std::ffi::CStr;
+use std::borrow::Cow;
 use std::str;
 
 use glib::translate::*;
@@ -17,6 +18,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..e32f8097 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -9,6 +9,7 @@ use std::ptr;
 use std::rc::Rc;
 use std::slice;
 use std::str;
+use std::borrow::Cow;
 
 use glib::translate::*;
 
@@ -17,13 +18,10 @@ use handle::LoadFlags;
 use io::get_input_stream_for_loading;
 use property_bag::PropertyBag;
 use util::utf8_cstr;
+use util::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,34 @@ 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]