From 535f219c413bdac983d265e75c141e5bf9c1ce9b Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Tue, 17 Feb 2015 23:10:38 -0800 Subject: [PATCH] Improved algorithm of Rope::append() It doesn't use an intermediate conversion to a string anymore, and should execute in O(log N) as long as the right-hand rope is equal length or smaller than the left. It may also be O(log N) for the left-hand rope being smaller, but that depends on whether the rebalance code executes in O(log N) time when the left and right hand side are individually balanced. I haven't analysed it yet, so dunno. --- src/buffer/rope.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/buffer/rope.rs b/src/buffer/rope.rs index ffc09e1..bf7a358 100644 --- a/src/buffer/rope.rs +++ b/src/buffer/rope.rs @@ -200,11 +200,17 @@ impl Rope { /// Appends another rope to the end of this one, consuming the other rope. pub fn append(&mut self, rope: Rope) { - // TODO: make more efficient. Converting to a string and then - // inserting is pretty slow... - let s = rope.to_string(); - let gc = self.grapheme_count(); - self.insert_text_at_grapheme_index(s.as_slice(), gc); + if self.tree_height <= rope.tree_height || self.is_leaf() { + let mut temp_rope = Box::new(Rope::new()); + mem::swap(self, &mut (*temp_rope)); + self.data = RopeData::Branch(temp_rope, Box::new(rope)); + } + else if let RopeData::Branch(_, ref mut right) = self.data { + right.append(rope); + } + + self.update_stats(); + self.rebalance(); } /// Makes a copy of the rope as a string