Skip to content

Commit b6fe920

Browse files
authored
Merge pull request #39 from yeggor/fix/search
use memchr::memmem for much faster search
2 parents cae8a1d + 6e6ec3b commit b6fe920

File tree

3 files changed

+19
-67
lines changed

3 files changed

+19
-67
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ license = "GPL-3.0-or-later"
1010
keywords = ["hex-editor", "reverse-engineering", "binary", "pe", "elf"]
1111
categories = ["command-line-utilities", "security"]
1212

13-
1413
[dependencies]
1514
arboard = { version = "3", default-features = false }
1615
clap = { version = "4.5.49", features = ["derive"] }
@@ -19,13 +18,14 @@ directories-next = "2.0.0"
1918
encoding_rs = "0.8.35"
2019
evalexpr = "13.1.*"
2120
hex = "0.4.3"
21+
memchr = "2.8.0"
22+
mmap-io = "0.9.4"
2223
ratatui = "0.30.0"
2324
regex = "1.11.2"
2425
serde = { version = "1.0.228", features = ["derive"] }
2526
shell-words = "1.1.0"
26-
tui-input = "0.15.0"
27-
mmap-io = { version = "0.9.4" }
2827
toml = "1.0.1"
28+
tui-input = "0.15.0"
2929

3030
# The profile that 'dist' will build with
3131
[profile.dist]

src/hex/search.rs

Lines changed: 15 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -51,40 +51,27 @@ pub fn hex_string_to_u8(hex_string: &str) -> Option<Vec<u8>> {
5151

5252
pub fn search<T: AsRef<[u8]>>(app: &mut App, needle: T) -> Option<usize> {
5353
let text = needle.as_ref();
54-
let siz = text.len();
5554
let filesize = app.file_info.size;
5655
let buffer = app.file_info.get_buffer();
5756

58-
if filesize == 0 {
57+
if filesize == 0 || text.is_empty() {
5958
return None;
6059
}
6160

62-
let search_forward = || {
63-
for (i, win) in buffer[app.hex_view.offset + 1..].windows(siz).enumerate() {
64-
if win == text {
65-
return Some(app.hex_view.offset + i + 1);
66-
}
67-
}
68-
None
69-
};
70-
71-
let search_backward = || {
72-
for (i, win) in buffer[0..app.hex_view.offset]
73-
.windows(siz)
74-
.rev()
75-
.enumerate()
76-
{
77-
if win == text {
78-
return Some(app.hex_view.offset - i - text.len());
79-
}
80-
}
81-
None
82-
};
83-
8461
let ofs = if app.hex_view.search.direction == SearchDirection::Forward {
85-
search_forward()
62+
let start = app.hex_view.offset.checked_add(1)?;
63+
if start < filesize {
64+
memchr::memmem::find(buffer.get(start..)?, text).map(|pos| start + pos)
65+
} else {
66+
None
67+
}
8668
} else {
87-
search_backward()
69+
let end = app.hex_view.offset;
70+
if end > 0 {
71+
memchr::memmem::rfind(buffer.get(..end)?, text)
72+
} else {
73+
None
74+
}
8875
};
8976

9077
if ofs.is_some() {
@@ -93,28 +80,10 @@ pub fn search<T: AsRef<[u8]>>(app: &mut App, needle: T) -> Option<usize> {
9380

9481
// ofs is None, check wrap setting
9582
if app.config.search_wrap {
96-
let search_wrap_forward = || {
97-
for (i, win) in buffer.windows(siz).enumerate() {
98-
if win == text {
99-
return Some(i);
100-
}
101-
}
102-
None
103-
};
104-
105-
let search_wrap_backward = || {
106-
for (i, win) in buffer.windows(siz).rev().enumerate() {
107-
if win == text {
108-
return Some(filesize - i - text.len());
109-
}
110-
}
111-
None
112-
};
113-
11483
let ofs = if app.hex_view.search.direction == SearchDirection::Forward {
115-
search_wrap_forward()
84+
memchr::memmem::find(buffer, text)
11685
} else {
117-
search_wrap_backward()
86+
memchr::memmem::rfind(buffer, text)
11887
};
11988

12089
if ofs.is_some() {
@@ -126,24 +95,6 @@ pub fn search<T: AsRef<[u8]>>(app: &mut App, needle: T) -> Option<usize> {
12695
None
12796
}
12897

129-
// pub fn search_back<T: AsRef<[u8]>>(app: &mut App, needle: T) -> Option<usize> {
130-
// let text = needle.as_ref();
131-
// let siz = text.len();
132-
// let buffer = app.file_info.get_buffer();
133-
// for (i, win) in buffer[0..app.hex_view.offset]
134-
// .windows(siz)
135-
// .rev()
136-
// .enumerate()
137-
// {
138-
// if win == text {
139-
// return Some(app.hex_view.offset - i - 1);
140-
// }
141-
// }
142-
//
143-
// crate::beep!();
144-
// None
145-
// }
146-
14798
// string
14899
// hex
149100
pub fn dialog_search_draw(app: &mut App, frame: &mut Frame) {

0 commit comments

Comments
 (0)