]> git.lizzy.rs Git - rust.git/commitdiff
Try to optimise char patterns
authorSimonas Kazlauskas <git@kazlauskas.me>
Mon, 15 May 2017 09:17:17 +0000 (12:17 +0300)
committerSimonas Kazlauskas <git@kazlauskas.me>
Fri, 19 May 2017 07:14:13 +0000 (10:14 +0300)
src/libcollections/benches/str.rs
src/libcollections/str.rs
src/libcore/str/pattern.rs

index 7f727078101c463ef62d85ca1c48e828d02bfa8c..fc4063fae927754353d5e736099f0a365b0dd2d7 100644 (file)
@@ -195,30 +195,34 @@ fn bench_contains_equal(b: &mut Bencher) {
     })
 }
 
+
 macro_rules! make_test_inner {
-    ($s:ident, $code:expr, $name:ident, $str:expr) => {
+    ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => {
         #[bench]
         fn $name(bencher: &mut Bencher) {
             let mut $s = $str;
             black_box(&mut $s);
-            bencher.iter(|| $code);
+            bencher.iter(|| for _ in 0..$iters { black_box($code); });
         }
     }
 }
 
 macro_rules! make_test {
     ($name:ident, $s:ident, $code:expr) => {
+        make_test!($name, $s, $code, 1);
+    };
+    ($name:ident, $s:ident, $code:expr, $iters:expr) => {
         mod $name {
             use test::Bencher;
             use test::black_box;
 
             // Short strings: 65 bytes each
             make_test_inner!($s, $code, short_ascii,
-                "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
+                "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters);
             make_test_inner!($s, $code, short_mixed,
-                "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
+                "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters);
             make_test_inner!($s, $code, short_pile_of_poo,
-                "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
+                "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters);
             make_test_inner!($s, $code, long_lorem_ipsum,"\
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
@@ -253,7 +257,7 @@ mod $name {
 feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
 vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
 leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
-malesuada sollicitudin quam eu fermentum!");
+malesuada sollicitudin quam eu fermentum!", $iters);
         }
     }
 }
@@ -288,6 +292,13 @@ mod $name {
 make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
 make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
 
+make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024);
+make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024);
+make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024);
+make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024);
+make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
+make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
+
 make_test!(split_space_char, s, s.split(' ').count());
 make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
 
index 5f4578bbeb36845ac862249368c73e4420e44063..7e67befb700dbcd16a5039cf6bdb26716417744b 100644 (file)
@@ -813,6 +813,7 @@ pub fn encode_utf16(&self) -> EncodeUtf16 {
     /// assert!(!bananas.contains("apples"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         core_str::StrExt::contains(self, pat)
     }
@@ -900,6 +901,7 @@ pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
     /// assert_eq!(s.find(x), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
         core_str::StrExt::find(self, pat)
     }
@@ -944,6 +946,7 @@ pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
     /// assert_eq!(s.rfind(x), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1057,6 +1060,7 @@ pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
     ///
     /// [`split_whitespace`]: #method.split_whitespace
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
         core_str::StrExt::split(self, pat)
     }
@@ -1106,6 +1110,7 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
     /// assert_eq!(v, ["ghi", "def", "abc"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1152,6 +1157,7 @@ pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
     /// assert_eq!(v, ["A", "", "B", ""]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
         core_str::StrExt::split_terminator(self, pat)
     }
@@ -1195,6 +1201,7 @@ pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator
     /// assert_eq!(v, ["", "B", "", "A"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1247,6 +1254,7 @@ pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminat
     /// assert_eq!(v, ["abc", "defXghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
         core_str::StrExt::splitn(self, n, pat)
     }
@@ -1294,6 +1302,7 @@ pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
     /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1334,6 +1343,7 @@ pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
     /// assert_eq!(v, ["1", "2", "3"]);
     /// ```
     #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
     pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
         core_str::StrExt::matches(self, pat)
     }
@@ -1370,6 +1380,7 @@ pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
     /// assert_eq!(v, ["3", "2", "1"]);
     /// ```
     #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
     pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1415,6 +1426,7 @@ pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
     /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
     /// ```
     #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
     pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
         core_str::StrExt::match_indices(self, pat)
     }
@@ -1457,6 +1469,7 @@ pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P
     /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
     /// ```
     #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
     pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1737,6 +1750,7 @@ pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
     /// assert_eq!(s, s.replace("cookie monster", "little lamb"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
         let mut result = String::new();
         let mut last_end = 0;
index 8493afe98bc5742b285c99bcd029af2b430ad42e..4918e37eb35f08a266122920a2def0a07bb2ea81 100644 (file)
@@ -429,7 +429,33 @@ impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
 
 /// Searches for chars that are equal to a given char
 impl<'a> Pattern<'a> for char {
-    pattern_methods!(CharSearcher<'a>, CharEqPattern, CharSearcher);
+    type Searcher = CharSearcher<'a>;
+
+    #[inline]
+    fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
+        CharSearcher(CharEqPattern(self).into_searcher(haystack))
+    }
+
+    #[inline]
+    fn is_contained_in(self, haystack: &'a str) -> bool {
+        if (self as u32) < 128 {
+            haystack.as_bytes().contains(&(self as u8))
+        } else {
+            let mut buffer = [0u8; 4];
+            self.encode_utf8(&mut buffer).is_contained_in(haystack)
+        }
+    }
+
+    #[inline]
+    fn is_prefix_of(self, haystack: &'a str) -> bool {
+        CharEqPattern(self).is_prefix_of(haystack)
+    }
+
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
+    {
+        CharEqPattern(self).is_suffix_of(haystack)
+    }
 }
 
 /////////////////////////////////////////////////////////////////////////////