Don't repeat yourself.

This commit is contained in:
David Wendt 2019-12-20 23:47:17 -05:00
parent bd1ea56cc3
commit 7a9a16e598
1 changed files with 24 additions and 23 deletions

View File

@ -20,61 +20,62 @@ pub struct XMLDocumentData<'gc> {
} }
impl<'gc> XMLDocument<'gc> { impl<'gc> XMLDocument<'gc> {
/// Construct a new, empty XML document.
pub fn new(mc: MutationContext<'gc, '_>) -> Self { pub fn new(mc: MutationContext<'gc, '_>) -> Self {
Self(GcCell::allocate(mc, XMLDocumentData { roots: Vec::new() })) Self(GcCell::allocate(mc, XMLDocumentData { roots: Vec::new() }))
} }
/// Ensure that a newly-encountered node is added to an ongoing parsing
/// stack, or to the document itself if the parsing stack is empty.
fn add_child_to_tree(
&mut self,
mc: MutationContext<'gc, '_>,
open_tags: &mut Vec<XMLNode<'gc>>,
child: XMLNode<'gc>,
) -> Result<(), Error> {
if let Some(node) = open_tags.last_mut() {
node.append_child(mc, child)?;
} else {
self.0.write(mc).roots.push(child);
}
Ok(())
}
pub fn from_str(mc: MutationContext<'gc, '_>, data: &str) -> Result<Self, Error> { pub fn from_str(mc: MutationContext<'gc, '_>, data: &str) -> Result<Self, Error> {
let mut parser = Reader::from_str(data); let mut parser = Reader::from_str(data);
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut roots = Vec::new(); let mut document = Self::new(mc);
let mut open_tags: Vec<XMLNode<'gc>> = Vec::new(); let mut open_tags: Vec<XMLNode<'gc>> = Vec::new();
loop { loop {
match parser.read_event(&mut buf)? { match parser.read_event(&mut buf)? {
Event::Start(bs) => { Event::Start(bs) => {
let child = XMLNode::from_start_event(mc, bs)?; let child = XMLNode::from_start_event(mc, bs)?;
if let Some(node) = open_tags.last_mut() { document.add_child_to_tree(mc, &mut open_tags, child)?;
node.append_child(mc, child)?;
} else {
roots.push(child);
}
open_tags.push(child); open_tags.push(child);
} }
Event::Empty(bs) => { Event::Empty(bs) => {
let child = XMLNode::from_start_event(mc, bs)?; let child = XMLNode::from_start_event(mc, bs)?;
if let Some(node) = open_tags.last_mut() { document.add_child_to_tree(mc, &mut open_tags, child)?;
node.append_child(mc, child)?;
} else {
roots.push(child);
}
} }
Event::End(_) => { Event::End(_) => {
open_tags.pop(); open_tags.pop();
} }
Event::Text(bt) => { Event::Text(bt) => {
let child = XMLNode::text_from_text_event(mc, bt)?; let child = XMLNode::text_from_text_event(mc, bt)?;
if let Some(node) = open_tags.last_mut() { document.add_child_to_tree(mc, &mut open_tags, child)?;
node.append_child(mc, child)?;
} else {
roots.push(child);
}
} }
Event::Comment(bt) => { Event::Comment(bt) => {
let child = XMLNode::comment_from_text_event(mc, bt)?; let child = XMLNode::comment_from_text_event(mc, bt)?;
if let Some(node) = open_tags.last_mut() { document.add_child_to_tree(mc, &mut open_tags, child)?;
node.append_child(mc, child)?;
} else {
roots.push(child);
}
} }
Event::Eof => break, Event::Eof => break,
_ => {} _ => {}
} }
} }
Ok(Self(GcCell::allocate(mc, XMLDocumentData { roots }))) Ok(document)
} }
/// Returns an iterator that yields the document's root nodes. /// Returns an iterator that yields the document's root nodes.