[librsvg: 9/48] Port the element_name_stack to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 9/48] Port the element_name_stack to Rust
- Date: Sat, 17 Nov 2018 10:20:47 +0000 (UTC)
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]