[librsvg: 4/18] Move storage of libxml2 entities to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 4/18] Move storage of libxml2 entities to Rust
- Date: Fri, 23 Nov 2018 22:31:49 +0000 (UTC)
commit 3fa37262050f53db256f60e9ceff2082413e6b76
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Nov 22 19:18:36 2018 -0600
Move storage of libxml2 entities to Rust
librsvg/rsvg-load.c | 27 +++++++------------
rsvg_internals/src/lib.rs | 2 ++
rsvg_internals/src/xml.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 17 deletions(-)
---
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 92e7833d..df73ee51 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -60,10 +60,15 @@ extern void rsvg_xml_state_end_element(RsvgXmlState *xml, RsvgHandle *handle, co
extern void rsvg_xml_state_characters(RsvgXmlState *xml, const char *unterminated_text, gsize len);
extern void rsvg_xml_state_error(RsvgXmlState *xml, const char *msg);
+extern xmlEntityPtr rsvg_xml_state_entity_lookup(RsvgXmlState *xml,
+ const char *entity_name);
+
+extern void rsvg_xml_state_entity_insert(RsvgXmlState *xml,
+ const char *entity_name,
+ xmlEntityPtr entity);
+
/* Holds the XML parsing state */
typedef struct {
- GHashTable *entities; /* g_malloc'd string -> xmlEntityPtr */
-
xmlParserCtxtPtr ctxt;
RsvgXmlState *rust_state;
@@ -99,10 +104,6 @@ rsvg_load_new (RsvgHandle *handle, gboolean unlimited_size)
load->error = NULL;
load->compressed_input_stream = NULL;
- load->xml.entities = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) xmlFreeNode);
load->xml.ctxt = NULL;
load->xml.rust_state = rsvg_xml_state_new ();
@@ -135,8 +136,6 @@ free_xml_parser_and_doc (xmlParserCtxtPtr ctxt)
void
rsvg_load_free (RsvgLoad *load)
{
- g_hash_table_destroy (load->xml.entities);
-
load->xml.ctxt = free_xml_parser_and_doc (load->xml.ctxt);
g_clear_object (&load->compressed_input_stream);
@@ -359,11 +358,8 @@ static xmlEntityPtr
sax_get_entity_cb (void *data, const xmlChar * name)
{
RsvgLoad *load = data;
- xmlEntityPtr entity;
-
- entity = g_hash_table_lookup (load->xml.entities, name);
- return entity;
+ return rsvg_xml_state_entity_lookup (load->xml.rust_state, (const char *) name);
}
static void
@@ -409,7 +405,7 @@ sax_entity_decl_cb (void *data, const xmlChar * name, int type,
xmlFree(resolvedPublicId);
xmlFree(resolvedSystemId);
- g_hash_table_insert (load->xml.entities, g_strdup ((const char*) name), entity);
+ rsvg_xml_state_entity_insert(load->xml.rust_state, (const char *) name, entity);
}
static void
@@ -425,11 +421,8 @@ static xmlEntityPtr
sax_get_parameter_entity_cb (void *data, const xmlChar * name)
{
RsvgLoad *load = data;
- xmlEntityPtr entity;
-
- entity = g_hash_table_lookup (load->xml.entities, name);
- return entity;
+ return rsvg_xml_state_entity_lookup (load->xml.rust_state, (const char *) name);
}
static void
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 0bdc2679..b74cd2de 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -68,6 +68,8 @@ pub use structure::rsvg_node_svg_get_size;
pub use xml::{
rsvg_xml_state_characters,
rsvg_xml_state_end_element,
+ rsvg_xml_state_entity_insert,
+ rsvg_xml_state_entity_lookup,
rsvg_xml_state_error,
rsvg_xml_state_free,
rsvg_xml_state_new,
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index a6dfa2ae..3cbec54d 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -3,6 +3,7 @@ use encoding::DecoderTrap;
use glib::translate::*;
use libc;
use std;
+use std::collections::HashMap;
use std::mem;
use std::ptr;
use std::rc::Rc;
@@ -73,6 +74,16 @@ impl Context {
// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}
+// This is to hold an xmlEntityPtr from libxml2; we just hold an opaque pointer
+// that is freed in impl Drop for XmlState
+type XmlEntityPtr = *mut libc::c_void;
+
+extern "C" {
+ // The original function takes an xmlNodePtr, but that is compatible
+ // with xmlEntityPtr for the purposes of this function.
+ fn xmlFreeNode(node: XmlEntityPtr);
+}
+
/// Holds the state used for XML processing
///
/// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
@@ -88,6 +99,8 @@ struct XmlState {
context: Context,
context_stack: Vec<Context>,
current_node: Option<Rc<Node>>,
+
+ entities: HashMap<String, XmlEntityPtr>,
}
/// Errors returned from XmlState::acquire()
@@ -110,6 +123,7 @@ impl XmlState {
context: Context::empty(),
context_stack: Vec::new(),
current_node: None,
+ entities: HashMap::new(),
}
}
@@ -199,6 +213,18 @@ impl XmlState {
self.push_context(Context::fatal_error());
}
+ pub fn entity_lookup(&self, entity_name: &str) -> Option<XmlEntityPtr> {
+ self.entities.get(entity_name).map(|v| *v)
+ }
+
+ pub fn entity_insert(&mut self, entity_name: &str, entity: XmlEntityPtr) {
+ let old_value = self.entities.insert(entity_name.to_string(), entity);
+
+ if let Some(v) = old_value {
+ unsafe { xmlFreeNode(v); }
+ }
+ }
+
fn element_creation_start_element(
&mut self,
handle: *mut RsvgHandle,
@@ -458,6 +484,16 @@ impl XmlState {
}
}
+impl Drop for XmlState {
+ fn drop(&mut self) {
+ unsafe {
+ for (_key, entity) in self.entities.drain() {
+ xmlFreeNode(entity);
+ }
+ }
+ }
+}
+
#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
@@ -558,3 +594,34 @@ pub unsafe extern "C" fn rsvg_xml_state_error(xml: *mut RsvgXmlState, msg: *cons
xml.error(&msg);
}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_xml_state_entity_lookup(
+ xml: *const RsvgXmlState,
+ entity_name: *const libc::c_char
+) -> XmlEntityPtr {
+ assert!(!xml.is_null());
+ let xml = &*(xml as *mut XmlState);
+
+ assert!(!entity_name.is_null());
+ let entity_name = utf8_cstr(entity_name);
+
+ xml.entity_lookup(entity_name).unwrap_or(ptr::null_mut())
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_xml_state_entity_insert(
+ xml: *mut RsvgXmlState,
+ entity_name: *const libc::c_char,
+ entity: XmlEntityPtr,
+) {
+ assert!(!xml.is_null());
+ let xml = &mut *(xml as *mut XmlState);
+
+ assert!(!entity_name.is_null());
+ let entity_name = utf8_cstr(entity_name);
+
+ assert!(!entity.is_null());
+
+ xml.entity_insert(entity_name, entity);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]