First attempt at self-balancing rope. Totally broken, though.
This commit is contained in:
parent
ab992301fd
commit
4f987ffa16
130
src/buffer.rs
130
src/buffer.rs
|
@ -1,6 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::{min, max};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std;
|
use std;
|
||||||
|
@ -161,6 +161,7 @@ impl fmt::Show for TextBlock {
|
||||||
// TODO: record number of graphines as well, to support utf8 properly
|
// TODO: record number of graphines as well, to support utf8 properly
|
||||||
pub struct TextNode {
|
pub struct TextNode {
|
||||||
pub data: TextNodeData,
|
pub data: TextNodeData,
|
||||||
|
pub tree_height: uint,
|
||||||
pub char_count: uint,
|
pub char_count: uint,
|
||||||
pub newline_count: uint,
|
pub newline_count: uint,
|
||||||
}
|
}
|
||||||
|
@ -178,6 +179,7 @@ impl TextNode {
|
||||||
pub fn new() -> TextNode {
|
pub fn new() -> TextNode {
|
||||||
TextNode {
|
TextNode {
|
||||||
data: TextNodeData::Leaf(TextBlock::new()),
|
data: TextNodeData::Leaf(TextBlock::new()),
|
||||||
|
tree_height: 1,
|
||||||
char_count: 0,
|
char_count: 0,
|
||||||
newline_count: 0,
|
newline_count: 0,
|
||||||
}
|
}
|
||||||
|
@ -186,11 +188,121 @@ impl TextNode {
|
||||||
pub fn new_from_str(text: &str) -> TextNode {
|
pub fn new_from_str(text: &str) -> TextNode {
|
||||||
TextNode {
|
TextNode {
|
||||||
data: TextNodeData::Leaf(TextBlock::new_from_str(text)),
|
data: TextNodeData::Leaf(TextBlock::new_from_str(text)),
|
||||||
|
tree_height: 1,
|
||||||
char_count: char_count(text),
|
char_count: char_count(text),
|
||||||
newline_count: newline_count(text),
|
newline_count: newline_count(text),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_height(&mut self) {
|
||||||
|
match self.data {
|
||||||
|
TextNodeData::Leaf(_) => {
|
||||||
|
self.tree_height = 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
TextNodeData::Branch(ref left, ref right) => {
|
||||||
|
self.tree_height = max(left.tree_height, right.tree_height) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate_left(&mut self) {
|
||||||
|
let mut temp = TextNode::new();
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(_, ref mut right) = self.data {
|
||||||
|
mem::swap(&mut temp, &mut (**right));
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(ref mut left, _) = temp.data {
|
||||||
|
mem::swap(left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(ref mut left, _) = temp.data {
|
||||||
|
mem::swap(&mut (**left), self);
|
||||||
|
left.update_height();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_height();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate_right(&mut self) {
|
||||||
|
let mut temp = TextNode::new();
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(ref mut left, _) = self.data {
|
||||||
|
mem::swap(&mut temp, &mut (**left));
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(_, ref mut right) = temp.data {
|
||||||
|
mem::swap(right, left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TextNodeData::Branch(_, ref mut right) = temp.data {
|
||||||
|
mem::swap(&mut (**right), self);
|
||||||
|
right.update_height();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_height();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rebalance(&mut self) {
|
||||||
|
loop {
|
||||||
|
let mut rot: int = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Left side higher than right side
|
||||||
|
if height_diff > 1 {
|
||||||
|
let mut child_rot = false;
|
||||||
|
if let TextNodeData::Branch(ref lc, ref rc) = left.data {
|
||||||
|
if lc.tree_height < rc.tree_height {
|
||||||
|
child_rot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if child_rot {
|
||||||
|
if let TextNodeData::Branch(_, ref mut rc) = right.data {
|
||||||
|
rc.rotate_right();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rot = 1;
|
||||||
|
}
|
||||||
|
// Right side higher then left side
|
||||||
|
else if height_diff < -1 {
|
||||||
|
let mut child_rot = false;
|
||||||
|
if let TextNodeData::Branch(ref lc, ref rc) = right.data {
|
||||||
|
if lc.tree_height > rc.tree_height {
|
||||||
|
child_rot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if child_rot {
|
||||||
|
if let TextNodeData::Branch(ref mut lc, _) = right.data {
|
||||||
|
lc.rotate_right();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rot = -1;
|
||||||
|
}
|
||||||
|
// Balanced, stop
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if rot == 1 {
|
||||||
|
self.rotate_right();
|
||||||
|
}
|
||||||
|
else if rot == 1 {
|
||||||
|
self.rotate_left();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Recursively splits a leaf node into roughly equal-sized children,
|
/// Recursively splits a leaf node into roughly equal-sized children,
|
||||||
/// being no larger than 'max_size'.
|
/// being no larger than 'max_size'.
|
||||||
pub fn split(&mut self, max_size: uint) {
|
pub fn split(&mut self, max_size: uint) {
|
||||||
|
@ -214,7 +326,11 @@ impl TextNode {
|
||||||
// Swap the old and new data
|
// Swap the old and new data
|
||||||
let mut new_data = TextNodeData::Branch(tn1, tn2);
|
let mut new_data = TextNodeData::Branch(tn1, tn2);
|
||||||
mem::swap(&mut self.data, &mut new_data);
|
mem::swap(&mut self.data, &mut new_data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.rebalance();
|
||||||
|
self.update_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merges the data of a non-leaf node to make it a leaf node
|
/// Merges the data of a non-leaf node to make it a leaf node
|
||||||
|
@ -238,6 +354,8 @@ impl TextNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.data = TextNodeData::Leaf(TextBlock::new_from_str(s.as_slice()));
|
self.data = TextNodeData::Leaf(TextBlock::new_from_str(s.as_slice()));
|
||||||
|
self.rebalance();
|
||||||
|
self.update_height();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +392,9 @@ impl TextNode {
|
||||||
self.newline_count = left.newline_count + right.newline_count;
|
self.newline_count = left.newline_count + right.newline_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.rebalance();
|
||||||
|
self.update_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the text between byte positions 'pos_a' and 'pos_b'.
|
/// Remove the text between byte positions 'pos_a' and 'pos_b'.
|
||||||
|
@ -311,8 +432,13 @@ impl TextNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.rebalance();
|
||||||
|
self.update_height();
|
||||||
|
|
||||||
if self.char_count < MIN_LEAF_SIZE {
|
if self.char_count < MIN_LEAF_SIZE {
|
||||||
self.merge();
|
self.merge();
|
||||||
|
self.rebalance();
|
||||||
|
self.update_height();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +463,7 @@ impl fmt::Show for TextNode {
|
||||||
|
|
||||||
/// A text buffer
|
/// A text buffer
|
||||||
pub struct TextBuffer {
|
pub struct TextBuffer {
|
||||||
root: TextNode
|
pub root: TextNode
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextBuffer {
|
impl TextBuffer {
|
||||||
|
|
|
@ -102,4 +102,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rustbox::shutdown();
|
rustbox::shutdown();
|
||||||
|
|
||||||
|
println!("{}", tb.root.tree_height);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user