mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Add util::tree::remove_child, and some tests. Add eq requirement for util::tree::WriteMethods
This commit is contained in:
parent
9c982693e1
commit
77c1b060fd
3 changed files with 119 additions and 11 deletions
|
@ -158,6 +158,8 @@ impl NodeScope : tree::WriteMethods<Node> {
|
||||||
tree::add_child(&self, node, child)
|
tree::add_child(&self, node, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pure fn eq(a: &Node, b: &Node) -> bool { a == b }
|
||||||
|
|
||||||
fn with_tree_fields<R>(node: &Node, f: fn(&tree::Tree<Node>) -> R) -> R {
|
fn with_tree_fields<R>(node: &Node, f: fn(&tree::Tree<Node>) -> R) -> R {
|
||||||
self.write(node, |n| f(&n.tree))
|
self.write(node, |n| f(&n.tree))
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,10 +326,11 @@ impl FlowTree : tree::ReadMethods<@FlowContext> {
|
||||||
|
|
||||||
impl FlowTree : tree::WriteMethods<@FlowContext> {
|
impl FlowTree : tree::WriteMethods<@FlowContext> {
|
||||||
fn add_child(parent: @FlowContext, child: @FlowContext) {
|
fn add_child(parent: @FlowContext, child: @FlowContext) {
|
||||||
assert !core::box::ptr_eq(parent, child);
|
|
||||||
tree::add_child(&self, parent, child)
|
tree::add_child(&self, parent, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pure fn eq(a: &@FlowContext, b: &@FlowContext) -> bool { core::box::ptr_eq(*a, *b) }
|
||||||
|
|
||||||
fn with_tree_fields<R>(box: &@FlowContext, f: fn(&tree::Tree<@FlowContext>) -> R) -> R {
|
fn with_tree_fields<R>(box: &@FlowContext, f: fn(&tree::Tree<@FlowContext>) -> R) -> R {
|
||||||
f(&box.d().tree)
|
f(&box.d().tree)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub trait ReadMethods<T> {
|
||||||
|
|
||||||
pub trait WriteMethods<T> {
|
pub trait WriteMethods<T> {
|
||||||
fn with_tree_fields<R>(&T, f: fn(&Tree<T>) -> R) -> R;
|
fn with_tree_fields<R>(&T, f: fn(&Tree<T>) -> R) -> R;
|
||||||
|
pure fn eq(&T, &T) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: fn(&T) -> bool) {
|
pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: fn(&T) -> bool) {
|
||||||
|
@ -42,6 +43,7 @@ pub fn empty<T>() -> Tree<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
|
pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
|
||||||
|
assert !ops.eq(&parent, &child);
|
||||||
|
|
||||||
ops.with_tree_fields(&child, |child_tf| {
|
ops.with_tree_fields(&child, |child_tf| {
|
||||||
match child_tf.parent {
|
match child_tf.parent {
|
||||||
|
@ -58,7 +60,6 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
|
||||||
parent_tf.first_child = Some(child);
|
parent_tf.first_child = Some(child);
|
||||||
}
|
}
|
||||||
Some(lc) => {
|
Some(lc) => {
|
||||||
let lc = lc; // satisfy alias checker
|
|
||||||
ops.with_tree_fields(&lc, |lc_tf| {
|
ops.with_tree_fields(&lc, |lc_tf| {
|
||||||
assert lc_tf.next_sibling.is_none();
|
assert lc_tf.next_sibling.is_none();
|
||||||
lc_tf.next_sibling = Some(child);
|
lc_tf.next_sibling = Some(child);
|
||||||
|
@ -72,36 +73,90 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
|
||||||
|
do ops.with_tree_fields(&child) |child_tf| {
|
||||||
|
match copy child_tf.parent {
|
||||||
|
None => { fail ~"Not a child"; }
|
||||||
|
Some(parent_n) => {
|
||||||
|
assert ops.eq(&parent, &parent_n);
|
||||||
|
|
||||||
|
// adjust parent fields
|
||||||
|
do ops.with_tree_fields(&parent) |parent_tf| {
|
||||||
|
match copy parent_tf.first_child {
|
||||||
|
None => { fail ~"parent had no first child??" },
|
||||||
|
Some(first_child) if ops.eq(&child, &first_child) => {
|
||||||
|
parent_tf.first_child = child_tf.next_sibling;
|
||||||
|
},
|
||||||
|
Some(_) => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
match copy parent_tf.last_child {
|
||||||
|
None => { fail ~"parent had no last child??" },
|
||||||
|
Some(last_child) if ops.eq(&child, &last_child) => {
|
||||||
|
parent_tf.last_child = child_tf.prev_sibling;
|
||||||
|
},
|
||||||
|
Some(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust siblings
|
||||||
|
match child_tf.prev_sibling {
|
||||||
|
None => {},
|
||||||
|
Some(_) => {
|
||||||
|
do ops.with_tree_fields(&child_tf.prev_sibling.get()) |prev_tf| {
|
||||||
|
prev_tf.next_sibling = child_tf.next_sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match child_tf.next_sibling {
|
||||||
|
None => {},
|
||||||
|
Some(_) => {
|
||||||
|
do ops.with_tree_fields(&child_tf.next_sibling.get()) |next_tf| {
|
||||||
|
next_tf.prev_sibling = child_tf.prev_sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear child
|
||||||
|
child_tf.parent = None;
|
||||||
|
child_tf.next_sibling = None;
|
||||||
|
child_tf.prev_sibling = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_parent<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> Option<T> {
|
pub fn get_parent<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> Option<T> {
|
||||||
ops.with_tree_fields(node, |tf| tf.parent)
|
ops.with_tree_fields(node, |tf| tf.parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
enum dummy = @{
|
enum dummy = {
|
||||||
fields: Tree<dummy>,
|
fields: Tree<@dummy>,
|
||||||
value: uint
|
value: uint
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dtree { dtree }
|
enum dtree { dtree }
|
||||||
|
|
||||||
impl dtree : ReadMethods<dummy> {
|
impl dtree : ReadMethods<@dummy> {
|
||||||
fn with_tree_fields<R>(d: &dummy, f: fn(&Tree<dummy>) -> R) -> R {
|
fn with_tree_fields<R>(d: &@dummy, f: fn(&Tree<@dummy>) -> R) -> R {
|
||||||
f(&d.fields)
|
f(&d.fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dtree : WriteMethods<dummy> {
|
impl dtree : WriteMethods<@dummy> {
|
||||||
fn with_tree_fields<R>(d: &dummy, f: fn(&Tree<dummy>) -> R) -> R {
|
fn with_tree_fields<R>(d: &@dummy, f: fn(&Tree<@dummy>) -> R) -> R {
|
||||||
f(&d.fields)
|
f(&d.fields)
|
||||||
}
|
}
|
||||||
|
pure fn eq(a: &@dummy, b: &@dummy) -> bool { core::box::ptr_eq(*a, *b) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_dummy(v: uint) -> dummy {
|
fn new_dummy(v: uint) -> @dummy {
|
||||||
dummy(@{fields: empty(), value: v})
|
@dummy({fields: empty(), value: v})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_with_3_children() -> {p: dummy, children: ~[dummy]} {
|
fn parent_with_3_children() -> {p: @dummy, children: ~[@dummy]} {
|
||||||
let children = ~[new_dummy(0u),
|
let children = ~[new_dummy(0u),
|
||||||
new_dummy(1u),
|
new_dummy(1u),
|
||||||
new_dummy(2u)];
|
new_dummy(2u)];
|
||||||
|
@ -135,4 +190,54 @@ mod test {
|
||||||
}
|
}
|
||||||
assert i == 1u;
|
assert i == 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_first_child() {
|
||||||
|
let {p, children} = parent_with_3_children();
|
||||||
|
remove_child(&dtree, p, children[0]);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for each_child(&dtree, &p) |_c| {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
assert i == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_last_child() {
|
||||||
|
let {p, children} = parent_with_3_children();
|
||||||
|
remove_child(&dtree, p, children[2]);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for each_child(&dtree, &p) |_c| {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
assert i == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_middle_child() {
|
||||||
|
let {p, children} = parent_with_3_children();
|
||||||
|
remove_child(&dtree, p, children[1]);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for each_child(&dtree, &p) |_c| {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
assert i == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_all_child() {
|
||||||
|
let {p, children} = parent_with_3_children();
|
||||||
|
remove_child(&dtree, p, children[0]);
|
||||||
|
remove_child(&dtree, p, children[1]);
|
||||||
|
remove_child(&dtree, p, children[2]);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for each_child(&dtree, &p) |_c| {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
assert i == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue