Text removal now works on text ropes.
This commit is contained in:
parent
65c900a237
commit
f85dd9c1db
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cmp::min;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ pub enum TextNodeData {
|
||||||
Branch(Box<TextNode>, Box<TextNode>)
|
Branch(Box<TextNode>, Box<TextNode>)
|
||||||
}
|
}
|
||||||
|
|
||||||
const MIN_LEAF_SIZE: uint = 512;
|
const MIN_LEAF_SIZE: uint = 64;
|
||||||
const MAX_LEAF_SIZE: uint = MIN_LEAF_SIZE * 2;
|
const MAX_LEAF_SIZE: uint = MIN_LEAF_SIZE * 2;
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,8 +156,7 @@ impl TextNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Splits a leaf node into equal-sized pieces until all children are
|
/// Splits a leaf node into two roughly equal-sized children
|
||||||
/// less than 'max_size'.
|
|
||||||
pub fn split(&mut self) {
|
pub fn split(&mut self) {
|
||||||
if let TextNodeData::Branch(_, _) = self.data {
|
if let TextNodeData::Branch(_, _) = self.data {
|
||||||
panic!("TextNode::split(): attempt to split a non-leaf node.");
|
panic!("TextNode::split(): attempt to split a non-leaf node.");
|
||||||
|
@ -212,9 +212,10 @@ impl TextNode {
|
||||||
TextNodeData::Leaf(_) => {
|
TextNodeData::Leaf(_) => {
|
||||||
if let TextNodeData::Leaf(ref mut tb) = self.data {
|
if let TextNodeData::Leaf(ref mut tb) = self.data {
|
||||||
tb.insert_text(text, pos);
|
tb.insert_text(text, pos);
|
||||||
|
|
||||||
|
self.newline_count += newline_count(text);
|
||||||
|
self.byte_count = tb.len();
|
||||||
}
|
}
|
||||||
self.newline_count += newline_count(text);
|
|
||||||
self.byte_count += text.len();
|
|
||||||
|
|
||||||
if self.byte_count > MAX_LEAF_SIZE {
|
if self.byte_count > MAX_LEAF_SIZE {
|
||||||
self.split();
|
self.split();
|
||||||
|
@ -234,6 +235,45 @@ impl TextNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove the text between byte positions 'pos_a' and 'pos_b'.
|
||||||
|
pub fn remove_text(&mut self, pos_a: uint, pos_b: uint) {
|
||||||
|
// Bounds checks
|
||||||
|
if pos_a > pos_b {
|
||||||
|
panic!("TextNode::remove_text(): pos_a must be less than or equal to pos_b.");
|
||||||
|
}
|
||||||
|
if pos_b > self.byte_count {
|
||||||
|
panic!("TextNode::remove_text(): attempt to remove text after end of node text.");
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.data {
|
||||||
|
TextNodeData::Leaf(ref mut tb) => {
|
||||||
|
tb.remove_text(pos_a, pos_b);
|
||||||
|
|
||||||
|
self.newline_count = newline_count(tb.as_str());
|
||||||
|
self.byte_count = tb.len();
|
||||||
|
},
|
||||||
|
|
||||||
|
TextNodeData::Branch(ref mut left, ref mut right) => {
|
||||||
|
let lbc = left.byte_count;
|
||||||
|
|
||||||
|
if pos_a < lbc {
|
||||||
|
left.remove_text(pos_a, min(pos_b, lbc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos_b > lbc {
|
||||||
|
right.remove_text(pos_a - min(pos_a, lbc), pos_b - lbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.newline_count = left.newline_count + right.newline_count;
|
||||||
|
self.byte_count = left.byte_count + right.byte_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.byte_count < MIN_LEAF_SIZE {
|
||||||
|
self.merge();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for TextNode {
|
impl fmt::Show for TextNode {
|
||||||
|
@ -277,14 +317,7 @@ impl TextBuffer {
|
||||||
|
|
||||||
/// Remove the text between byte positions 'pos_a' and 'pos_b'.
|
/// Remove the text between byte positions 'pos_a' and 'pos_b'.
|
||||||
pub fn remove_text(&mut self, pos_a: uint, pos_b: uint) {
|
pub fn remove_text(&mut self, pos_a: uint, pos_b: uint) {
|
||||||
match self.root.data {
|
self.root.remove_text(pos_a, pos_b);
|
||||||
TextNodeData::Leaf(ref mut tb) => {
|
|
||||||
tb.remove_text(pos_a, pos_b);
|
|
||||||
self.root.byte_count = tb.len();
|
|
||||||
},
|
|
||||||
|
|
||||||
TextNodeData::Branch(_, _) => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -32,12 +32,14 @@ fn main() {
|
||||||
|
|
||||||
let mut tb = TextBuffer::new();
|
let mut tb = TextBuffer::new();
|
||||||
|
|
||||||
for _ in range(0i, 100) {
|
for _ in range(0i, 1000) {
|
||||||
tb.insert_text(args.arg_file.as_slice(), 0);
|
tb.insert_text(args.arg_file.as_slice(), 0);
|
||||||
//if tb.len() > 1024 {
|
if tb.len() > 1024 {
|
||||||
// tb.remove_text(0, args.arg_file.len());
|
tb.remove_text(27, 27+3);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tb.remove_text(3, 6);
|
||||||
|
|
||||||
println!("{}", tb);
|
println!("{}", tb);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user