diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-01-11 18:01:10 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-01-11 18:01:10 -0800 |
| commit | 7c66a5c1216f334bfa29bddd7e4c3a451900efbb (patch) | |
| tree | d1308f8bdbac9816d5192c6b21d2ebbe2692231f /src | |
| parent | 03bc0d13fa7f1809521b70843ffd50e327a77fdf (diff) | |
| download | editor-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.rs | 19 | ||||
| -rw-r--r-- | src/rope.rs | 19 |
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"); + } + } + } } |
