[librsvg: 4/18] Move storage of libxml2 entities to Rust



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]