diff options
| author | bors <bors@rust-lang.org> | 2021-03-19 00:47:37 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-03-19 00:47:37 +0000 |
| commit | eb95acea8aeaeef834214eaffb15d64095fe9271 (patch) | |
| tree | 1e13b205c657ee7584e35bf301bace177ef64bc5 /library/alloc/src/string.rs | |
| parent | 1705a7d64b833d1c4b69958b0627bd054e6d764b (diff) | |
| parent | a2571cfc8b6f5cf5d8d2e7075ac4809aceae9541 (diff) | |
| download | rust-eb95acea8aeaeef834214eaffb15d64095fe9271.tar.gz rust-eb95acea8aeaeef834214eaffb15d64095fe9271.zip | |
Auto merge of #71780 - jcotton42:string_remove_matches, r=joshtriplett
Implement String::remove_matches Closes #50206. I lifted the function help from `@frewsxcv's` original PR (#50015), hope they don't mind. I'm also wondering whether it would be useful for `remove_matches` to collect up the removed substrings into a `Vec` and return them, right now they're just overwritten by the copy and lost.
Diffstat (limited to 'library/alloc/src/string.rs')
| -rw-r--r-- | library/alloc/src/string.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e2e705d7980..019b17a5945 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1202,6 +1202,62 @@ impl String { ch } + /// Remove all matches of pattern `pat` in the `String`. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("Trees are not green, the sky is not blue."); + /// s.remove_matches("not "); + /// assert_eq!("Trees are green, the sky is blue.", s); + /// ``` + /// + /// Matches will be detected and removed iteratively, so in cases where + /// patterns overlap, only the first pattern will be removed: + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("banana"); + /// s.remove_matches("ana"); + /// assert_eq!("bna", s); + /// ``` + #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] + pub fn remove_matches<'a, P>(&'a mut self, pat: P) + where + P: for<'x> Pattern<'x>, + { + use core::str::pattern::Searcher; + + let matches = { + let mut searcher = pat.into_searcher(self); + let mut matches = Vec::new(); + + while let Some(m) = searcher.next_match() { + matches.push(m); + } + + matches + }; + + let len = self.len(); + let mut shrunk_by = 0; + + // SAFETY: start and end will be on utf8 byte boundaries per + // the Searcher docs + unsafe { + for (start, end) in matches { + ptr::copy( + self.vec.as_mut_ptr().add(end - shrunk_by), + self.vec.as_mut_ptr().add(start - shrunk_by), + len - end, + ); + shrunk_by += end - start; + } + self.vec.set_len(len - shrunk_by); + } + } + /// Retains only the characters specified by the predicate. /// /// In other words, remove all characters `c` such that `f(c)` returns `false`. |
