Commit c8dafbf7 authored by Kornel's avatar Kornel

Use libxml's structured error callback instead of vararg one

parent 79e4acf2
......@@ -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)
{
......
......@@ -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;
......
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
......
......@@ -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::*;
......
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment