Port the element_name_stack to Rust

parent 2ca3daf7
......@@ -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;
......
......@@ -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]
......
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();
}
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