[librsvg: 9/48] Port the element_name_stack to Rust



commit fb42d16ce5626003dcbcd33228e704e7e32b5eaa
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Sep 6 19:41:48 2018 -0500

    Port the element_name_stack to Rust

 librsvg/rsvg-load.c       | 50 +++++--------------------------
 rsvg_internals/src/lib.rs |  4 +++
 rsvg_internals/src/xml.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+), 42 deletions(-)
---
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 6a4c6cd9..92851469 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -63,6 +63,10 @@ extern void rsvg_xml_state_set_root (RsvgXmlState *xml, RsvgNode *root);
 extern RsvgTree *rsvg_xml_state_steal_tree(RsvgXmlState *xml);
 extern RsvgNode *rsvg_xml_state_get_current_node(RsvgXmlState *xml);
 extern void rsvg_xml_state_set_current_node(RsvgXmlState *xml, RsvgNode *node);
+extern void rsvg_xml_state_push_element_name(RsvgXmlState *xml, const char *name);
+extern void rsvg_xml_state_pop_element_name(RsvgXmlState *xml);
+extern gboolean rsvg_xml_state_topmost_element_name_is(RsvgXmlState *xml, const char *name);
+extern void rsvg_xml_state_free_element_name_stack(RsvgXmlState *xml);
 
 /* Holds the XML parsing state */
 typedef struct {
@@ -76,11 +80,6 @@ typedef struct {
 
     xmlParserCtxtPtr ctxt;
 
-    /* Stack of element names while parsing; used to know when to stop parsing
-     * the current element.
-     */
-    GSList *element_name_stack;
-
     RsvgXmlState *rust_state;
 } XmlState;
 
@@ -136,7 +135,6 @@ rsvg_load_new (RsvgHandle *handle, gboolean unlimited_size)
                                                 g_free,
                                                 (GDestroyNotify) xmlFreeNode);
     load->xml.ctxt = NULL;
-    load->xml.element_name_stack = NULL;
     load->xml.rust_state = rsvg_xml_state_new ();
 
     return load;
@@ -267,38 +265,6 @@ start_style (RsvgLoad *load, RsvgPropertyBag *atts)
     rsvg_property_bag_iter_end (iter);
 }
 
-static void
-push_element_name (RsvgLoad *load, const char *name)
-{
-    /* libxml holds on to the name while parsing; we won't dup the name here */
-    load->xml.element_name_stack = g_slist_prepend (load->xml.element_name_stack, (void *) name);
-}
-
-static gboolean
-topmost_element_name_is (RsvgLoad *load, const char *name)
-{
-    if (load->xml.element_name_stack) {
-        const char *name_in_stack = load->xml.element_name_stack->data;
-
-        return strcmp (name, name_in_stack) == 0;
-    } else
-        return FALSE;
-}
-
-static void
-pop_element_name (RsvgLoad *load)
-{
-    load->xml.element_name_stack = g_slist_delete_link (load->xml.element_name_stack,
-                                                        load->xml.element_name_stack);
-}
-
-static void
-free_element_name_stack (RsvgLoad *load)
-{
-    g_slist_free (load->xml.element_name_stack);
-    load->xml.element_name_stack = NULL;
-}
-
 static void
 standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts)
 {
@@ -312,7 +278,7 @@ standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts
 
     newnode = rsvg_load_new_node (name, current_node, atts, defs);
 
-    push_element_name (load, name);
+    rsvg_xml_state_push_element_name (load->xml.rust_state, name);
 
     if (current_node) {
         rsvg_node_add_child (current_node, newnode);
@@ -672,14 +638,14 @@ sax_end_element_cb (void *data, const xmlChar * xmlname)
             rsvg_load_set_svg_node_atts (load->handle, current_node);
         }
 
-        if (current_node && topmost_element_name_is (load, name)) {
+        if (current_node && rsvg_xml_state_topmost_element_name_is (load->xml.rust_state, name)) {
             RsvgNode *parent;
 
             parent = rsvg_node_get_parent (current_node);
             rsvg_xml_state_set_current_node (load->xml.rust_state, parent);
             parent = rsvg_node_unref (parent);
 
-            pop_element_name (load);
+            rsvg_xml_state_pop_element_name (load->xml.rust_state);
         }
 
         current_node = rsvg_node_unref (current_node);
@@ -1030,7 +996,7 @@ close_impl (RsvgLoad *load, GError ** error)
         load->xml.ctxt = free_xml_parser_and_doc (load->xml.ctxt);
     }
 
-    free_element_name_stack (load);
+    rsvg_xml_state_free_element_name_stack (load->xml.rust_state);
 
     load->error = NULL;
 
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index bb89a22b..4e7e6df2 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -79,11 +79,15 @@ pub use text::{rsvg_node_chars_append, rsvg_node_chars_new};
 
 pub use xml::{
     rsvg_xml_state_free,
+    rsvg_xml_state_free_element_name_stack,
     rsvg_xml_state_get_current_node,
     rsvg_xml_state_new,
+    rsvg_xml_state_pop_element_name,
+    rsvg_xml_state_push_element_name,
     rsvg_xml_state_set_current_node,
     rsvg_xml_state_set_root,
     rsvg_xml_state_steal_tree,
+    rsvg_xml_state_topmost_element_name_is,
 };
 
 #[macro_use]
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index e279eb5e..41dcb202 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -1,8 +1,13 @@
+use libc;
 use std::ptr;
 use std::rc::Rc;
 
+use glib::translate::*;
+use glib_sys;
+
 use node::{box_node, Node, RsvgNode};
 use tree::{RsvgTree, Tree};
+use util::utf8_cstr;
 
 // A *const RsvgXmlState is just the type that we export to C
 pub enum RsvgXmlState {}
@@ -10,6 +15,10 @@ pub enum RsvgXmlState {}
 struct XmlState {
     tree: Option<Box<Tree>>,
     current_node: Option<Rc<Node>>,
+
+    // Stack of element names while parsing; used to know when to stop
+    // parsing the current element.
+    element_name_stack: Vec<String>,
 }
 
 impl XmlState {
@@ -17,6 +26,7 @@ impl XmlState {
         XmlState {
             tree: None,
             current_node: None,
+            element_name_stack: Vec::new(),
         }
     }
 
@@ -39,6 +49,28 @@ impl XmlState {
     pub fn set_current_node(&mut self, node: Option<Rc<Node>>) {
         self.current_node = node;
     }
+
+    pub fn push_element_name(&mut self, name: &str) {
+        self.element_name_stack.push(name.to_string());
+    }
+
+    pub fn pop_element_name(&mut self) {
+        self.element_name_stack.pop();
+    }
+
+    pub fn topmost_element_name_is(&mut self, name: &str) -> bool {
+        let len = self.element_name_stack.len();
+
+        if len > 0 {
+            self.element_name_stack[len - 1] == name
+        } else {
+            false
+        }
+    }
+
+    pub fn free_element_name_stack(&mut self) {
+        self.element_name_stack.clear();
+    }
 }
 
 #[no_mangle]
@@ -107,3 +139,47 @@ pub extern "C" fn rsvg_xml_state_set_current_node(
 
     xml.set_current_node(node);
 }
+
+#[no_mangle]
+pub extern "C" fn rsvg_xml_state_push_element_name(
+    xml: *mut RsvgXmlState,
+    name: *const libc::c_char,
+) {
+    assert!(!xml.is_null());
+    let xml = unsafe { &mut *(xml as *mut XmlState) };
+
+    assert!(!name.is_null());
+
+    let name = unsafe { utf8_cstr(name) };
+    xml.push_element_name(name);
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_xml_state_pop_element_name(xml: *mut RsvgXmlState) {
+    assert!(!xml.is_null());
+    let xml = unsafe { &mut *(xml as *mut XmlState) };
+
+    xml.pop_element_name();
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_xml_state_topmost_element_name_is(
+    xml: *mut RsvgXmlState,
+    name: *const libc::c_char,
+) -> glib_sys::gboolean {
+    assert!(!xml.is_null());
+    let xml = unsafe { &mut *(xml as *mut XmlState) };
+
+    assert!(!name.is_null());
+
+    let name = unsafe { utf8_cstr(name) };
+    xml.topmost_element_name_is(name).to_glib()
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState) {
+    assert!(!xml.is_null());
+    let xml = unsafe { &mut *(xml as *mut XmlState) };
+
+    xml.free_element_name_stack();
+}


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