From ef64bd8f1c228bc029aafc4b677b1f5151595998 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Fri, 19 Dec 2014 00:23:08 -0800 Subject: [PATCH] Fixed bug in tree balancing. Text rope is now fully self-balancing. --- src/buffer.rs | 49 +++++++++++++++++++++++++++++++++-------- src/main.rs | 60 ++++++++++++++++++++++++++++----------------------- 2 files changed, 73 insertions(+), 36 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 307134b..78053a1 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -206,6 +206,23 @@ impl TextNode { } } + pub fn update_stats(&mut self) { + match self.data { + TextNodeData::Leaf(ref tb) => { + self.tree_height = 1; + let (cc, nlc) = char_and_newline_count(tb.as_str()); + self.char_count = cc; + self.newline_count = nlc; + }, + + TextNodeData::Branch(ref left, ref right) => { + self.tree_height = max(left.tree_height, right.tree_height) + 1; + self.char_count = left.char_count + right.char_count; + self.newline_count = left.newline_count + right.newline_count; + } + } + } + pub fn rotate_left(&mut self) { let mut temp = TextNode::new(); @@ -213,16 +230,23 @@ impl TextNode { mem::swap(&mut temp, &mut (**right)); if let TextNodeData::Branch(ref mut left, _) = temp.data { - mem::swap(left, right); + mem::swap(&mut (**left), &mut (**right)); } + else { + panic!("rotate_left(): attempting to rotate node without branching right child."); + } + } + else { + panic!("rotate_left(): attempting to rotate leaf node."); } if let TextNodeData::Branch(ref mut left, _) = temp.data { mem::swap(&mut (**left), self); - left.update_height(); + left.update_stats(); } - self.update_height(); + mem::swap(&mut temp, self); + self.update_stats(); } pub fn rotate_right(&mut self) { @@ -232,21 +256,28 @@ impl TextNode { mem::swap(&mut temp, &mut (**left)); if let TextNodeData::Branch(_, ref mut right) = temp.data { - mem::swap(right, left); + mem::swap(&mut (**right), &mut (**left)); } + else { + panic!("rotate_right(): attempting to rotate node without branching left child."); + } + } + else { + panic!("rotate_right(): attempting to rotate leaf node."); } if let TextNodeData::Branch(_, ref mut right) = temp.data { mem::swap(&mut (**right), self); - right.update_height(); + right.update_stats(); } - self.update_height(); + mem::swap(&mut temp, self); + self.update_stats(); } pub fn rebalance(&mut self) { loop { - let mut rot: int = 0; + let mut rot: int; if let TextNodeData::Branch(ref mut left, ref mut right) = self.data { let height_diff = (left.tree_height as int) - (right.tree_height as int); @@ -262,7 +293,7 @@ impl TextNode { if child_rot { if let TextNodeData::Branch(_, ref mut rc) = right.data { - rc.rotate_right(); + rc.rotate_left(); } } @@ -297,7 +328,7 @@ impl TextNode { if rot == 1 { self.rotate_right(); } - else if rot == 1 { + else if rot == -1 { self.rotate_left(); } } diff --git a/src/main.rs b/src/main.rs index 7004709..d3f8e66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate rustbox; extern crate docopt; extern crate serialize; + use std::char; use docopt::Docopt; use buffer::TextBuffer; @@ -39,40 +40,44 @@ fn main() { rustbox::init(); + let enough_time_has_passed: bool = true; + loop { // Draw the text buffer to screen - rustbox::clear(); - { - let mut tb_iter = tb.root_iter(); - let mut line: uint = 0; - let mut column: uint = 0; - - loop { - if let Option::Some(c) = tb_iter.next() { - if c == '\n' { + if enough_time_has_passed { + rustbox::clear(); + { + let mut tb_iter = tb.root_iter(); + let mut line: uint = 0; + let mut column: uint = 0; + + loop { + if let Option::Some(c) = tb_iter.next() { + if c == '\n' { + line += 1; + column = 0; + continue; + } + rustbox::print(column, line, Style::Normal, Color::White, Color::Black, c.to_string()); + column += 1; + } + else { + break; + } + + if line > height { + break; + } + + if column > width { + tb_iter.next_line(); line += 1; column = 0; - continue; } - rustbox::print(column, line, Style::Normal, Color::White, Color::Black, c.to_string()); - column += 1; - } - else { - break; - } - - if line > height { - break; - } - - if column > width { - tb_iter.next_line(); - line += 1; - column = 0; } } + rustbox::present(); } - rustbox::present(); // Handle events match rustbox::poll_event() { @@ -98,9 +103,10 @@ fn main() { height = h as uint; } - _ => { } + _ => {break;} } } + rustbox::shutdown(); println!("{}", tb.root.tree_height);