aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-01-11 18:01:10 -0800
committerRose Hogenson <rosehogenson@posteo.net>2024-01-11 18:01:10 -0800
commit7c66a5c1216f334bfa29bddd7e4c3a451900efbb (patch)
treed1308f8bdbac9816d5192c6b21d2ebbe2692231f /src
parent03bc0d13fa7f1809521b70843ffd50e327a77fdf (diff)
downloadeditor-7c66a5c1216f334bfa29bddd7e4c3a451900efbb.tar.zst
Optimise line_offset for the ASCII case.
In most cases we really won't need the full binary search. We can check quickly for ASCII without ever printing anything, and fall back to binary search if we find any Unicode characters.
Diffstat (limited to 'src')
-rw-r--r--src/main.rs19
-rw-r--r--src/rope.rs19
2 files changed, 38 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
index 2b6a814..0dfe335 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,6 +20,25 @@ fn line_offset(
line: &Rope,
col: u16,
) -> Result<usize, Box<dyn Error>> {
+ let mut n = 0;
+ for i in 0.. {
+ if i == line.len() {
+ return Ok(i);
+ }
+ let c = line.byte(i);
+ if c > 127 {
+ break;
+ }
+ if n == col {
+ return Ok(i);
+ }
+ if c == b'\t' {
+ n += 8 - n % 8;
+ } else {
+ n += 1;
+ }
+ }
+
// Binary search :D
let mut lo = 0;
let mut hi = line.len() + 1;
diff --git a/src/rope.rs b/src/rope.rs
index 31c3296..737d949 100644
--- a/src/rope.rs
+++ b/src/rope.rs
@@ -355,4 +355,23 @@ impl Rope {
}
}
}
+
+ pub fn byte(&self, i: usize) -> u8 {
+ if i >= self.len() {
+ panic!("Index {} out of range 0..{}", i, self.len());
+ }
+ match self {
+ Rope(Node::Leaf(l)) => l.bytes()[i],
+ Rope(Node::Branch(b)) => {
+ let mut i = i;
+ for c in b.children().iter() {
+ if i < c.len() {
+ return c.byte(i);
+ }
+ i -= c.len();
+ }
+ panic!("unreachable");
+ }
+ }
+ }
}