Skip to content

Commit bccc8f4

Browse files
committed
Simplify strip_basedirs a bit more
1 parent fb5d0fb commit bccc8f4

File tree

1 file changed

+26
-40
lines changed

1 file changed

+26
-40
lines changed

src/util.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,43 +1033,29 @@ pub fn strip_basedirs(preprocessor_output: &[u8], basedirs: &[PathBuf]) -> Vec<u
10331033
return preprocessor_output.to_vec();
10341034
}
10351035

1036-
// Prepare normalized basedirs sorted by length (longest first) to match longest prefix first
1037-
let basedirs_data: Vec<_> = basedirs
1038-
.iter()
1039-
.map(|basedir| {
1040-
let basedir_str = basedir.to_string_lossy();
1041-
let trimmed = basedir_str.trim_end_matches('/').trim_end_matches('\\');
1042-
let normalized = normalize_path(trimmed.as_bytes());
1043-
(trimmed.as_bytes().to_vec(), normalized, trimmed.len())
1044-
})
1045-
.filter(|(bytes, _, _)| !bytes.is_empty())
1046-
.collect();
1047-
1048-
if basedirs_data.is_empty() {
1049-
return preprocessor_output.to_vec();
1050-
}
1051-
10521036
trace!(
10531037
"Stripping basedirs from preprocessor output with length {}: {:?}",
10541038
preprocessor_output.len(),
10551039
basedirs
10561040
);
10571041

10581042
// Find all potential matches for each basedir using fast substring search
1059-
// Store as (position, basedir_index, length) sorted by position
1060-
let mut matches: Vec<(usize, usize, usize)> = Vec::new();
1043+
// Store as (position, length) sorted by position
1044+
let mut matches: Vec<(usize, usize)> = Vec::new();
10611045
#[cfg(target_os = "windows")]
1062-
let preprocessor_output_normalized = normalize_path(preprocessor_output);
1063-
1064-
for (basedir_idx, basedir) in basedirs_data.iter().enumerate() {
1065-
let basedir_len = basedir.2;
1066-
// Use memchr's fast substring search
1067-
// Case sensitive
1068-
#[cfg(not(target_os = "windows"))]
1069-
let finder = memchr::memmem::find_iter(preprocessor_output, &basedir.0);
1070-
// Case insensitive
1046+
let preprocessor_output = &normalize_path(preprocessor_output);
1047+
1048+
for basedir_path in basedirs.iter() {
1049+
let basedir_str = basedir_path.to_string_lossy();
1050+
let basedir = basedir_str
1051+
.trim_end_matches('/')
1052+
.trim_end_matches('\\')
1053+
.as_bytes();
10711054
#[cfg(target_os = "windows")]
1072-
let finder = memchr::memmem::find_iter(&preprocessor_output_normalized, &basedir.1);
1055+
// Case insensitive
1056+
let basedir = normalize_path(basedir);
1057+
// Use memchr's fast substring search
1058+
let finder = memchr::memmem::find_iter(preprocessor_output, &basedir);
10731059

10741060
for pos in finder {
10751061
// Check if this is a valid boundary (start, whitespace, quote, or '<')
@@ -1079,7 +1065,7 @@ pub fn strip_basedirs(preprocessor_output: &[u8], basedirs: &[PathBuf]) -> Vec<u
10791065
|| preprocessor_output[pos - 1] == b'<';
10801066

10811067
if is_boundary {
1082-
matches.push((pos, basedir_idx, basedir_len));
1068+
matches.push((pos, basedir.len()));
10831069
}
10841070
}
10851071
}
@@ -1089,13 +1075,13 @@ pub fn strip_basedirs(preprocessor_output: &[u8], basedirs: &[PathBuf]) -> Vec<u
10891075
}
10901076

10911077
// Sort matches by position, then by length descending (longest first for overlaps)
1092-
matches.sort_by(|a, b| a.0.cmp(&b.0).then(b.2.cmp(&a.2)));
1078+
matches.sort_by(|a, b| a.0.cmp(&b.0).then(b.1.cmp(&a.1)));
10931079

10941080
// Remove overlapping matches, keeping the longest match at each position
10951081
let mut filtered_matches: Vec<(usize, usize)> = Vec::new();
10961082
let mut last_end = 0;
10971083

1098-
for (pos, _basedir_idx, len) in matches {
1084+
for (pos, len) in matches {
10991085
if pos >= last_end {
11001086
filtered_matches.push((pos, len));
11011087
last_end = pos + len;
@@ -1124,6 +1110,10 @@ pub fn strip_basedirs(preprocessor_output: &[u8], basedirs: &[PathBuf]) -> Vec<u
11241110
/// Normalize path for case-insensitive comparison.
11251111
/// On Windows: converts all backslashes to forward slashes;
11261112
/// lowercases ASCII characters for consistency.
1113+
/// This function used for two purposes:
1114+
/// - basedir_path: already normalized by std::path::absolute,
1115+
/// but still can mismatch the case of the actual file name
1116+
/// - preprocessor_output: plain text
11271117
#[cfg(target_os = "windows")]
11281118
fn normalize_path(path: &[u8]) -> Vec<u8> {
11291119
path.iter()
@@ -1135,11 +1125,6 @@ fn normalize_path(path: &[u8]) -> Vec<u8> {
11351125
.collect()
11361126
}
11371127

1138-
#[cfg(not(target_os = "windows"))]
1139-
fn normalize_path(path: &[u8]) -> Vec<u8> {
1140-
path.to_vec()
1141-
}
1142-
11431128
#[cfg(test)]
11441129
mod tests {
11451130
use super::{OsStrExt, TimeMacroFinder};
@@ -1407,14 +1392,15 @@ mod tests {
14071392
let basedir = PathBuf::from("C:\\Users\\test\\project");
14081393
let input = b"# 1 \"C:\\Users\\test\\project\\src\\main.c\"";
14091394
let output = super::strip_basedirs(input, std::slice::from_ref(&basedir));
1410-
let expected = b"# 1 \".\\src\\main.c\"";
1395+
// normalized backslash to slash
1396+
let expected = b"# 1 \"./src/main.c\"";
14111397
assert_eq!(output, expected);
14121398

14131399
// With multiple trailing backslashes
14141400
let basedir = PathBuf::from("C:\\Users\\test\\project\\\\\\");
14151401
let input = b"# 1 \"C:\\Users\\test\\project\\src\\main.c\"";
14161402
let output = super::strip_basedirs(input, std::slice::from_ref(&basedir));
1417-
let expected = b"# 1 \".\\src\\main.c\"";
1403+
let expected = b"# 1 \"./src/main.c\"";
14181404
assert_eq!(output, expected);
14191405
}
14201406

@@ -1427,13 +1413,13 @@ mod tests {
14271413
let basedir = PathBuf::from("C:\\Users\\test\\project");
14281414
let input = b"# 1 \"C:/Users\\test\\project\\src/main.c\"";
14291415
let output = super::strip_basedirs(input, std::slice::from_ref(&basedir));
1430-
let expected = b"# 1 \".\\src/main.c\"";
1416+
let expected = b"# 1 \"./src/main.c\"";
14311417
assert_eq!(output, expected, "Failed to strip mixed slash path");
14321418

14331419
// Also test the reverse case
14341420
let input = b"# 1 \"C:\\Users/test/project/src\\main.c\"";
14351421
let output = super::strip_basedirs(input, std::slice::from_ref(&basedir));
1436-
let expected = b"# 1 \"./src\\main.c\"";
1422+
let expected = b"# 1 \"./src/main.c\"";
14371423
assert_eq!(output, expected, "Failed to strip reverse mixed slash path");
14381424
}
14391425
}

0 commit comments

Comments
 (0)