diff options
author | Colin Finck <colin@reactos.org> | 2021-08-02 00:18:14 +0300 |
---|---|---|
committer | Colin Finck <colin@reactos.org> | 2021-08-02 00:18:14 +0300 |
commit | 6210c625de3f617b0553ae8176f2483133517161 (patch) | |
tree | 09ed0a59abd45e1c5691c652011baf2733184e8e /src/string.rs | |
parent | 943309f22ed6e208b7dcc1b24ae8879eb88f8a39 (diff) |
Implement finding files by name in a file name index.
This introduces parsing the $UpCase file to perform case-insensitive searches.
Diffstat (limited to 'src/string.rs')
-rw-r--r-- | src/string.rs | 77 |
1 files changed, 64 insertions, 13 deletions
diff --git a/src/string.rs b/src/string.rs index ce0109b..2d6d4a9 100644 --- a/src/string.rs +++ b/src/string.rs @@ -1,10 +1,11 @@ // Copyright 2021 Colin Finck <colin@reactos.org> // SPDX-License-Identifier: GPL-2.0-or-later +use crate::ntfs::Ntfs; use alloc::string::String; use core::char; use core::cmp::Ordering; -use core::convert::TryInto; +use core::convert::{identity, TryInto}; use core::fmt; /// Zero-copy representation of a string stored in an NTFS filesystem structure. @@ -12,17 +13,21 @@ use core::fmt; pub struct NtfsString<'a>(pub &'a [u8]); impl<'a> NtfsString<'a> { - fn cmp_iter<TI, OI>(mut this_iter: TI, mut other_iter: OI) -> Ordering + fn cmp_iter<TI, OI, F>(mut this_iter: TI, mut other_iter: OI, code_unit_fn: F) -> Ordering where TI: Iterator<Item = u16>, OI: Iterator<Item = u16>, + F: Fn(u16) -> u16, { loop { match (this_iter.next(), other_iter.next()) { (Some(this_code_unit), Some(other_code_unit)) => { // We have two UTF-16 code units to compare. - if this_code_unit != other_code_unit { - return this_code_unit.cmp(&other_code_unit); + let this_upper = code_unit_fn(this_code_unit); + let other_upper = code_unit_fn(other_code_unit); + + if this_upper != other_upper { + return this_upper.cmp(&other_upper); } } (Some(_), None) => { @@ -91,7 +96,7 @@ impl<'a> fmt::Display for NtfsString<'a> { impl<'a> Ord for NtfsString<'a> { fn cmp(&self, other: &Self) -> Ordering { - NtfsString::cmp_iter(self.u16_iter(), other.u16_iter()) + NtfsString::cmp_iter(self.u16_iter(), other.u16_iter(), identity) } } @@ -104,25 +109,25 @@ impl<'a> PartialEq for NtfsString<'a> { impl<'a> PartialEq<str> for NtfsString<'a> { fn eq(&self, other: &str) -> bool { - NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16()) == Ordering::Equal + NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16(), identity) == Ordering::Equal } } impl<'a> PartialEq<NtfsString<'a>> for str { fn eq(&self, other: &NtfsString<'a>) -> bool { - NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter()) == Ordering::Equal + NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter(), identity) == Ordering::Equal } } impl<'a> PartialEq<&str> for NtfsString<'a> { fn eq(&self, other: &&str) -> bool { - NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16()) == Ordering::Equal + NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16(), identity) == Ordering::Equal } } impl<'a> PartialEq<NtfsString<'a>> for &str { fn eq(&self, other: &NtfsString<'a>) -> bool { - NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter()) == Ordering::Equal + NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter(), identity) == Ordering::Equal } } @@ -134,24 +139,70 @@ impl<'a> PartialOrd for NtfsString<'a> { impl<'a> PartialOrd<str> for NtfsString<'a> { fn partial_cmp(&self, other: &str) -> Option<Ordering> { - Some(NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16())) + Some(NtfsString::cmp_iter( + self.u16_iter(), + other.encode_utf16(), + identity, + )) } } impl<'a> PartialOrd<NtfsString<'a>> for str { fn partial_cmp(&self, other: &NtfsString<'a>) -> Option<Ordering> { - Some(NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter())) + Some(NtfsString::cmp_iter( + self.encode_utf16(), + other.u16_iter(), + identity, + )) } } impl<'a> PartialOrd<&str> for NtfsString<'a> { fn partial_cmp(&self, other: &&str) -> Option<Ordering> { - Some(NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16())) + Some(NtfsString::cmp_iter( + self.u16_iter(), + other.encode_utf16(), + identity, + )) } } impl<'a> PartialOrd<NtfsString<'a>> for &str { fn partial_cmp(&self, other: &NtfsString<'a>) -> Option<Ordering> { - Some(NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter())) + Some(NtfsString::cmp_iter( + self.encode_utf16(), + other.u16_iter(), + identity, + )) + } +} + +pub trait UpcaseOrd<Rhs> { + /// Performs a case-insensitive ordering based on the upcase table read from the filesystem. + /// + /// # Panics + /// + /// Panics if [`read_upcase_table`][Ntfs::read_upcase_table] had not been called on the passed [`Ntfs`] object. + fn upcase_cmp(&self, ntfs: &Ntfs, other: &Rhs) -> Ordering; +} + +impl<'a> UpcaseOrd<NtfsString<'a>> for NtfsString<'a> { + fn upcase_cmp(&self, ntfs: &Ntfs, other: &NtfsString<'a>) -> Ordering { + let upcase_fn = |x| ntfs.upcase_table().u16_to_uppercase(x); + NtfsString::cmp_iter(self.u16_iter(), other.u16_iter(), upcase_fn) + } +} + +impl<'a> UpcaseOrd<&str> for NtfsString<'a> { + fn upcase_cmp(&self, ntfs: &Ntfs, other: &&str) -> Ordering { + let upcase_fn = |x| ntfs.upcase_table().u16_to_uppercase(x); + NtfsString::cmp_iter(self.u16_iter(), other.encode_utf16(), upcase_fn) + } +} + +impl<'a> UpcaseOrd<NtfsString<'a>> for &str { + fn upcase_cmp(&self, ntfs: &Ntfs, other: &NtfsString<'a>) -> Ordering { + let upcase_fn = |x| ntfs.upcase_table().u16_to_uppercase(x); + NtfsString::cmp_iter(self.encode_utf16(), other.u16_iter(), upcase_fn) } } |