xml.rs: New file; start moving the XML parsing state to Rust

parent 2261bc6d
......@@ -116,7 +116,8 @@ RUST_SRC = \
rsvg_internals/src/unitinterval.rs \
rsvg_internals/src/util.rs \
rsvg_internals/src/viewbox.rs \
rsvg_internals/src/viewport.rs
rsvg_internals/src/viewport.rs \
rsvg_internals/src/xml.rs
RUST_EXTRA = \
Cargo.lock \
......
......@@ -53,6 +53,15 @@ void rsvg_load_set_svg_node_atts (RsvgHandle *handle, RsvgNode *node);
G_GNUC_INTERNAL
void rsvg_node_register_in_defs(RsvgNode *node, RsvgDefs *defs);
/* Implemented in rsvg_internals/src/xml.rs */
typedef struct RsvgXmlState RsvgXmlState;
/* Implemented in rsvg_internals/src/xml.rs */
extern RsvgXmlState *rsvg_xml_state_new ();
extern void rsvg_xml_state_free (RsvgXmlState *xml);
extern void rsvg_xml_state_set_root (RsvgXmlState *xml, RsvgNode *root);
extern RsvgTree *rsvg_xml_state_steal_tree(RsvgXmlState *xml);
/* Holds the XML parsing state */
typedef struct {
/* not a handler stack. each nested handler keeps
......@@ -70,8 +79,9 @@ typedef struct {
*/
GSList *element_name_stack;
RsvgTree *tree;
RsvgNode *currentnode;
RsvgXmlState *rust_state;
} XmlState;
/* Holds the GIO and loading state for compressed data */
......@@ -127,8 +137,8 @@ rsvg_load_new (RsvgHandle *handle, gboolean unlimited_size)
(GDestroyNotify) xmlFreeNode);
load->xml.ctxt = NULL;
load->xml.element_name_stack = NULL;
load->xml.tree = NULL;
load->xml.currentnode = NULL;
load->xml.rust_state = rsvg_xml_state_new ();
return load;
}
......@@ -165,14 +175,14 @@ rsvg_load_free (RsvgLoad *load)
g_clear_object (&load->compressed_input_stream);
g_clear_pointer (&load->xml.currentnode, rsvg_node_unref);
g_clear_pointer (&load->xml.tree, rsvg_tree_free);
g_clear_pointer (&load->xml.rust_state, rsvg_xml_state_free);
g_free (load);
}
RsvgTree *
rsvg_load_steal_tree (RsvgLoad *load)
{
return g_steal_pointer (&load->xml.tree);
return rsvg_xml_state_steal_tree (load->xml.rust_state);
}
static void
......@@ -307,7 +317,7 @@ standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts
rsvg_node_add_child (load->xml.currentnode, newnode);
load->xml.currentnode = rsvg_node_unref (load->xml.currentnode);
} else if (is_svg) {
load->xml.tree = rsvg_tree_new (newnode);
rsvg_xml_state_set_root (load->xml.rust_state, newnode);
}
load->xml.currentnode = rsvg_node_ref (newnode);
......@@ -1194,7 +1204,7 @@ rsvg_load_close (RsvgLoad *load, GError **error)
}
if (!res) {
g_clear_pointer (&load->xml.tree, rsvg_tree_free);
g_clear_pointer (&load->xml.rust_state, rsvg_xml_state_free);
}
load->state = LOAD_STATE_CLOSED;
......
......@@ -166,10 +166,6 @@ gboolean rsvg_node_children_iter_next_back (RsvgNodeChildrenIter *iter,
G_GNUC_INTERNAL
void rsvg_node_children_iter_end (RsvgNodeChildrenIter *iter);
/* Implemented in rsvg_internals/src/tree.rs */
G_GNUC_INTERNAL
RsvgTree *rsvg_tree_new (RsvgNode *root);
/* Implemented in rsvg_internals/src/tree.rs */
G_GNUC_INTERNAL
void rsvg_tree_free (RsvgTree *tree);
......
......@@ -62,7 +62,6 @@ pub use tree::{
rsvg_tree_free,
rsvg_tree_get_root,
rsvg_tree_is_root,
rsvg_tree_new,
rsvg_tree_root_is_svg,
};
......@@ -78,6 +77,13 @@ pub use structure::rsvg_node_svg_get_size;
pub use text::{rsvg_node_chars_append, rsvg_node_chars_new};
pub use xml::{
rsvg_xml_state_free,
rsvg_xml_state_new,
rsvg_xml_state_set_root,
rsvg_xml_state_steal_tree,
};
#[macro_use]
mod log;
......@@ -134,3 +140,4 @@ mod unitinterval;
mod util;
mod viewbox;
mod viewport;
mod xml;
......@@ -35,14 +35,6 @@ impl Tree {
}
}
#[no_mangle]
pub extern "C" fn rsvg_tree_new(root: *const RsvgNode) -> *mut RsvgTree {
assert!(!root.is_null());
let root: &RsvgNode = unsafe { &*root };
Box::into_raw(Box::new(Tree::new(root))) as *mut RsvgTree
}
#[no_mangle]
pub extern "C" fn rsvg_tree_free(tree: *mut RsvgTree) {
if !tree.is_null() {
......
use std::ptr;
use std::rc::Rc;
use node::{Node, RsvgNode};
use tree::{RsvgTree, Tree};
// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}
struct XmlState {
tree: Option<Box<Tree>>,
}
impl XmlState {
fn new() -> XmlState {
XmlState { tree: None }
}
pub fn set_root(&mut self, root: &Rc<Node>) {
if self.tree.is_some() {
panic!("The tree root has already been set");
}
self.tree = Some(Box::new(Tree::new(root)));
}
pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
self.tree.take()
}
}
#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}
#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
assert!(!xml.is_null());
let xml = unsafe { &mut *(xml as *mut XmlState) };
unsafe {
Box::from_raw(xml);
}
}
#[no_mangle]
pub extern "C" fn rsvg_xml_state_set_root(xml: *mut RsvgXmlState, root: *const RsvgNode) {
assert!(!xml.is_null());
let xml = unsafe { &mut *(xml as *mut XmlState) };
assert!(!root.is_null());
let root = unsafe { &*root };
xml.set_root(root);
}
#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
assert!(!xml.is_null());
let xml = unsafe { &mut *(xml as *mut XmlState) };
if let Some(tree) = xml.steal_tree() {
Box::into_raw(tree) as *mut RsvgTree
} else {
ptr::null_mut()
}
}
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