Skip to content

Commit 1d14691

Browse files
Improve code style
1 parent b450aee commit 1d14691

File tree

1 file changed

+70
-45
lines changed

1 file changed

+70
-45
lines changed

text/grep.rs

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::{
1616
fs::File,
1717
io::{self, BufRead, BufReader, StdoutLock, Write},
1818
path::{Path, PathBuf},
19+
ptr,
1920
};
2021

2122
/// grep - search a file for a pattern.
@@ -303,13 +304,13 @@ impl Patterns {
303304
/// # Returns
304305
///
305306
/// Returns [bool](bool) - `true` if input matches present patterns, else `false`.
306-
fn matches(
307-
&self,
308-
input: impl AsRef<str>,
309-
collect_matching_substrings: bool,
310-
) -> (bool, Vec<Vec<u8>>) {
307+
fn matches(&self, input: impl AsRef<str>, collect_matching_substrings: bool) -> MatchesResult {
311308
let input = input.as_ref();
312309

310+
let mut matching_substrings = Vec::<Vec<u8>>::new();
311+
312+
let mut any_pattern_matched = false;
313+
313314
match self {
314315
Patterns::Fixed(patterns, ignore_case, line_regexp) => {
315316
let input = if *ignore_case {
@@ -318,18 +319,14 @@ impl Patterns {
318319
input.to_string()
319320
};
320321

321-
let mut matching_substrings = Vec::<Vec<u8>>::new();
322-
323-
let mut any_pattern_matched = false;
324-
325322
for pattern in patterns {
326323
if *line_regexp {
327324
if input != *pattern {
328325
continue;
329326
}
330327

331328
if !collect_matching_substrings {
332-
return (true, Vec::<Vec<u8>>::new());
329+
return MatchesResult::fast_path_match();
333330
}
334331

335332
any_pattern_matched = true;
@@ -338,7 +335,7 @@ impl Patterns {
338335
} else {
339336
for st in input.matches(pattern) {
340337
if !collect_matching_substrings {
341-
return (true, Vec::<Vec<u8>>::new());
338+
return MatchesResult::fast_path_match();
342339
}
343340

344341
any_pattern_matched = true;
@@ -347,45 +344,45 @@ impl Patterns {
347344
}
348345
}
349346
}
350-
351-
(any_pattern_matched, matching_substrings)
352347
}
353348
Patterns::Regex(patterns) => {
354-
let nmatch_to_use = if collect_matching_substrings { 1 } else { 0 };
349+
const SINGLE_ELEMENT_ARRAY_SIZE: usize = 1_usize;
355350

356351
let input_slice = input.as_bytes();
357352

358-
let mut matching_substrings = Vec::<Vec<u8>>::new();
353+
let mut regmatch_t_array = [const {
354+
regmatch_t {
355+
rm_so: -1,
356+
rm_eo: -1,
357+
}
358+
}; SINGLE_ELEMENT_ARRAY_SIZE];
359359

360-
let mut any_pattern_matched = false;
360+
let (nmatch, pmatch) = if collect_matching_substrings {
361+
(SINGLE_ELEMENT_ARRAY_SIZE, regmatch_t_array.as_mut_ptr())
362+
} else {
363+
(0_usize, ptr::null_mut())
364+
};
361365

362-
for p in patterns {
366+
for pattern in patterns {
363367
let mut current_string_index = 0_usize;
364368

365369
loop {
370+
// Clear values from the last iteration
371+
if collect_matching_substrings {
372+
let [ref mut regmatch_t] = regmatch_t_array;
373+
374+
regmatch_t.rm_so = -1;
375+
regmatch_t.rm_eo = -1;
376+
}
377+
366378
let current_string_slice = &input_slice[current_string_index..];
367379

368380
let current_string_c_string = CString::new(current_string_slice).unwrap();
369381

370-
let mut regmatch_t_vec = vec![
371-
regmatch_t {
372-
rm_so: -1,
373-
rm_eo: -1,
374-
};
375-
nmatch_to_use
376-
];
377-
378-
let regmatch_vec_pointer = regmatch_t_vec.as_mut_ptr();
379-
380-
let regexec_return_value = unsafe {
381-
regexec(
382-
p,
383-
current_string_c_string.as_ptr(),
384-
nmatch_to_use,
385-
regmatch_vec_pointer,
386-
0,
387-
)
388-
};
382+
let current_string_pointer = current_string_c_string.as_ptr();
383+
384+
let regexec_return_value =
385+
unsafe { regexec(pattern, current_string_pointer, nmatch, pmatch, 0) };
389386

390387
if regexec_return_value != 0 {
391388
debug_assert!(regexec_return_value == REG_NOMATCH);
@@ -394,15 +391,20 @@ impl Patterns {
394391
}
395392

396393
if !collect_matching_substrings {
397-
return (true, Vec::<Vec<u8>>::new());
394+
return MatchesResult::fast_path_match();
398395
}
399396

400397
any_pattern_matched = true;
401398

402-
let regmatch_t = regmatch_t_vec.first().unwrap();
399+
let [regmatch_t] = regmatch_t_array;
403400

404-
let start = usize::try_from(regmatch_t.rm_so).unwrap();
405-
let end = usize::try_from(regmatch_t.rm_eo).unwrap();
401+
let regmatch_t { rm_so, rm_eo } = regmatch_t;
402+
403+
debug_assert!(rm_so != -1);
404+
debug_assert!(rm_eo != -1);
405+
406+
let start = usize::try_from(rm_so).unwrap();
407+
let end = usize::try_from(rm_eo).unwrap();
406408

407409
// TODO
408410
// Is this the right fix?
@@ -418,10 +420,13 @@ impl Patterns {
418420
current_string_index += end;
419421
}
420422
}
421-
422-
(any_pattern_matched, matching_substrings)
423423
}
424424
}
425+
426+
MatchesResult {
427+
any_pattern_matched,
428+
matching_substrings,
429+
}
425430
}
426431
}
427432

@@ -462,6 +467,21 @@ struct GrepModel {
462467
only_matching: bool,
463468
}
464469

470+
struct MatchesResult {
471+
any_pattern_matched: bool,
472+
/// Will always be empty if the -o option is not being used
473+
matching_substrings: Vec<Vec<u8>>,
474+
}
475+
476+
impl MatchesResult {
477+
pub fn fast_path_match() -> MatchesResult {
478+
MatchesResult {
479+
any_pattern_matched: true,
480+
matching_substrings: Vec::<Vec<u8>>::new(),
481+
}
482+
}
483+
}
484+
465485
impl GrepModel {
466486
/// Processes input files or STDIN content.
467487
///
@@ -542,15 +562,20 @@ impl GrepModel {
542562
_ => line.as_str(),
543563
};
544564

545-
let (line_matches_any_pattern, matching_substrings) = self.patterns.matches(
565+
let matches_result = self.patterns.matches(
546566
line_without_newline,
547567
self.only_matching && matches!(self.output_mode, OutputMode::Default),
548568
);
549569

570+
let MatchesResult {
571+
any_pattern_matched,
572+
matching_substrings,
573+
} = matches_result;
574+
550575
let matches = if self.invert_match {
551-
!line_matches_any_pattern
576+
!any_pattern_matched
552577
} else {
553-
line_matches_any_pattern
578+
any_pattern_matched
554579
};
555580

556581
if matches {

0 commit comments

Comments
 (0)