]> git.lizzy.rs Git - rust.git/blobdiff - src/libregex/re.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / libregex / re.rs
index 91b24888c24fa1cfa1ae2d7a704db52225473b45..c2578d227ee384839d806da04f1e9de374134a17 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use collections::HashMap;
+use std::collections::HashMap;
 use std::fmt;
 use std::from_str::from_str;
 use std::str::{MaybeOwned, Owned, Slice};
 use vm;
 use vm::{CaptureLocs, MatchKind, Exists, Location, Submatches};
 
-/// Escapes all regular expression meta characters in `text` so that it may be
-/// safely used in a regular expression as a literal string.
+/// Escapes all regular expression meta characters in `text`.
+///
+/// The string returned may be safely used as a literal in a regular
+/// expression.
 pub fn quote(text: &str) -> String {
     let mut quoted = String::with_capacity(text.len());
     for c in text.chars() {
@@ -45,9 +47,10 @@ pub fn is_match(regex: &str, text: &str) -> Result<bool, parse::Error> {
     Regex::new(regex).map(|r| r.is_match(text))
 }
 
-/// Regex is a compiled regular expression, represented as either a sequence
-/// of bytecode instructions (dynamic) or as a specialized Rust function
-/// (native). It can be used to search, split
+/// A compiled regular expression
+///
+/// It is represented as either a sequence of bytecode instructions (dynamic)
+/// or as a specialized Rust function (native). It can be used to search, split
 /// or replace text. All searching is done with an implicit `.*?` at the
 /// beginning and end of an expression. To force an expression to match the
 /// whole string (or a prefix or a suffix), you must use an anchor like `^` or
@@ -55,7 +58,7 @@ pub fn is_match(regex: &str, text: &str) -> Result<bool, parse::Error> {
 ///
 /// While this crate will handle Unicode strings (whether in the regular
 /// expression or in the search text), all positions returned are **byte
-/// indices**. Every byte index is guaranteed to be at a UTF8 codepoint
+/// indices**. Every byte index is guaranteed to be at a Unicode code point
 /// boundary.
 ///
 /// The lifetimes `'r` and `'t` in this crate correspond to the lifetime of a
@@ -84,7 +87,7 @@ pub fn is_match(regex: &str, text: &str) -> Result<bool, parse::Error> {
 /// ```rust
 /// #![feature(phase)]
 /// extern crate regex;
-/// #[phase(syntax)] extern crate regex_macros;
+/// #[phase(plugin)] extern crate regex_macros;
 ///
 /// fn main() {
 ///     let re = regex!(r"\d+");
@@ -107,14 +110,14 @@ pub enum Regex {
     // See the comments for the `program` module in `lib.rs` for a more
     // detailed explanation for what `regex!` requires.
     #[doc(hidden)]
-    Dynamic(Dynamic),
+    Dynamic(ExDynamic),
     #[doc(hidden)]
-    Native(Native),
+    Native(ExNative),
 }
 
 #[deriving(Clone)]
 #[doc(hidden)]
-pub struct Dynamic {
+pub struct ExDynamic {
     original: String,
     names: Vec<Option<String>>,
     #[doc(hidden)]
@@ -122,7 +125,7 @@ pub struct Dynamic {
 }
 
 #[doc(hidden)]
-pub struct Native {
+pub struct ExNative {
     #[doc(hidden)]
     pub original: &'static str,
     #[doc(hidden)]
@@ -131,8 +134,8 @@ pub struct Native {
     pub prog: fn(MatchKind, &str, uint, uint) -> Vec<Option<uint>>
 }
 
-impl Clone for Native {
-    fn clone(&self) -> Native { *self }
+impl Clone for ExNative {
+    fn clone(&self) -> ExNative { *self }
 }
 
 impl fmt::Show for Regex {
@@ -153,8 +156,8 @@ impl Regex {
     pub fn new(re: &str) -> Result<Regex, parse::Error> {
         let ast = try!(parse::parse(re));
         let (prog, names) = Program::new(ast);
-        Ok(Dynamic(Dynamic {
-            original: re.to_strbuf(),
+        Ok(Dynamic(ExDynamic {
+            original: re.to_string(),
             names: names,
             prog: prog,
         }))
@@ -169,7 +172,7 @@ pub fn new(re: &str) -> Result<Regex, parse::Error> {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "I categorically deny having triskaidekaphobia.";
     /// let matched = regex!(r"\b\w{13}\b").is_match(text);
@@ -189,12 +192,12 @@ pub fn is_match(&self, text: &str) -> bool {
     ///
     /// # Example
     ///
-    /// Find the start and end location of every word with exactly 13
+    /// Find the start and end location of the first word with exactly 13
     /// characters:
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "I categorically deny having triskaidekaphobia.";
     /// let pos = regex!(r"\b\w{13}\b").find(text);
@@ -204,7 +207,7 @@ pub fn is_match(&self, text: &str) -> bool {
     pub fn find(&self, text: &str) -> Option<(uint, uint)> {
         let caps = exec(self, Location, text);
         if has_match(&caps) {
-            Some((caps.get(0).unwrap(), caps.get(1).unwrap()))
+            Some((caps[0].unwrap(), caps[1].unwrap()))
         } else {
             None
         }
@@ -216,12 +219,12 @@ pub fn find(&self, text: &str) -> Option<(uint, uint)> {
     ///
     /// # Example
     ///
-    /// Find the start and end location of the first word with exactly 13
+    /// Find the start and end location of every word with exactly 13
     /// characters:
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "Retroactively relinquishing remunerations is reprehensible.";
     /// for pos in regex!(r"\b\w{13}\b").find_iter(text) {
@@ -260,7 +263,7 @@ pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> FindMatches<'r, 't> {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'([^']+)'\s+\((\d{4})\)");
     /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
@@ -278,7 +281,7 @@ pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> FindMatches<'r, 't> {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
     /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
@@ -311,7 +314,7 @@ pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
     /// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
@@ -347,7 +350,7 @@ pub fn captures_iter<'r, 't>(&'r self, text: &'t str)
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"[ \t]+");
     /// let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
@@ -377,7 +380,7 @@ pub fn split<'r, 't>(&'r self, text: &'t str) -> RegexSplits<'r, 't> {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"\W+");
     /// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
@@ -407,7 +410,7 @@ pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: uint)
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!("[^01]+");
     /// assert_eq!(re.replace("1078910", "").as_slice(), "1010");
@@ -421,11 +424,11 @@ pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: uint)
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # use regex::Captures; fn main() {
     /// let re = regex!(r"([^,\s]+),\s+(\S+)");
     /// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
-    ///     format_strbuf!("{} {}", caps.at(2), caps.at(1))
+    ///     format!("{} {}", caps.at(2), caps.at(1))
     /// });
     /// assert_eq!(result.as_slice(), "Bruce Springsteen");
     /// # }
@@ -438,7 +441,7 @@ pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: uint)
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)");
     /// let result = re.replace("Springsteen, Bruce", "$first $last");
@@ -455,7 +458,7 @@ pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: uint)
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// use regex::NoExpand;
     ///
@@ -507,8 +510,8 @@ pub fn replacen<R: Replacer>
     /// Returns the original string of this regex.
     pub fn as_str<'a>(&'a self) -> &'a str {
         match *self {
-            Dynamic(Dynamic { ref original, .. }) => original.as_slice(),
-            Native(Native { ref original, .. }) => original.as_slice(),
+            Dynamic(ExDynamic { ref original, .. }) => original.as_slice(),
+            Native(ExNative { ref original, .. }) => original.as_slice(),
         }
     }
 
@@ -539,8 +542,8 @@ enum NamesIter<'a> {
 impl<'a> Iterator<Option<String>> for NamesIter<'a> {
     fn next(&mut self) -> Option<Option<String>> {
         match *self {
-            NamesIterNative(ref mut i) => i.next().map(|x| x.map(|s| s.to_strbuf())),
-            NamesIterDynamic(ref mut i) => i.next().map(|x| x.as_ref().map(|s| s.to_strbuf())),
+            NamesIterNative(ref mut i) => i.next().map(|x| x.map(|s| s.to_string())),
+            NamesIterDynamic(ref mut i) => i.next().map(|x| x.as_ref().map(|s| s.to_string())),
         }
     }
 }
@@ -573,13 +576,13 @@ fn reg_replace<'a>(&'a mut self, _: &Captures) -> MaybeOwned<'a> {
 
 impl<'t> Replacer for &'t str {
     fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> {
-        Owned(caps.expand(*self).into_owned())
+        Owned(caps.expand(*self))
     }
 }
 
-impl<'a> Replacer for |&Captures|: 'a -> String {
-    fn reg_replace<'r>(&'r mut self, caps: &Captures) -> MaybeOwned<'r> {
-        Owned((*self)(caps).into_owned())
+impl<'t> Replacer for |&Captures|: 't -> String {
+    fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> {
+        Owned((*self)(caps))
     }
 }
 
@@ -696,11 +699,11 @@ fn new(re: &Regex, search: &'t str, locs: CaptureLocs)
     /// original string matched.
     pub fn pos(&self, i: uint) -> Option<(uint, uint)> {
         let (s, e) = (i * 2, i * 2 + 1);
-        if e >= self.locs.len() || self.locs.get(s).is_none() {
+        if e >= self.locs.len() || self.locs[s].is_none() {
             // VM guarantees that each pair of locations are both Some or None.
             return None
         }
-        Some((self.locs.get(s).unwrap(), self.locs.get(e).unwrap()))
+        Some((self.locs[s].unwrap(), self.locs[e].unwrap()))
     }
 
     /// Returns the matched string for the capture group `i`.
@@ -761,11 +764,10 @@ pub fn expand(&self, text: &str) -> String {
         let re = Regex::new(r"(^|[^$]|\b)\$(\w+)").unwrap();
         let text = re.replace_all(text, |refs: &Captures| -> String {
             let (pre, name) = (refs.at(1), refs.at(2));
-            format_strbuf!("{}{}",
-                           pre,
-                           match from_str::<uint>(name.as_slice()) {
-                None => self.name(name).to_strbuf(),
-                Some(i) => self.at(i).to_strbuf(),
+            format!("{}{}", pre,
+                    match from_str::<uint>(name.as_slice()) {
+                None => self.name(name).to_string(),
+                Some(i) => self.at(i).to_string(),
             })
         });
         let re = Regex::new(r"\$\$").unwrap();
@@ -773,7 +775,7 @@ pub fn expand(&self, text: &str) -> String {
     }
 }
 
-impl<'t> Container for Captures<'t> {
+impl<'t> Collection for Captures<'t> {
     /// Returns the number of captured groups.
     #[inline]
     fn len(&self) -> uint {
@@ -824,8 +826,9 @@ fn next(&mut self) -> Option<Option<(uint, uint)>> {
 }
 
 /// An iterator that yields all non-overlapping capture groups matching a
-/// particular regular expression. The iterator stops when no more matches can
-/// be found.
+/// particular regular expression.
+///
+/// The iterator stops when no more matches can be found.
 ///
 /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime
 /// of the matched string.
@@ -848,7 +851,7 @@ fn next(&mut self) -> Option<Captures<'t>> {
             if !has_match(&caps) {
                 return None
             } else {
-                (caps.get(0).unwrap(), caps.get(1).unwrap())
+                (caps[0].unwrap(), caps[1].unwrap())
             };
 
         // Don't accept empty matches immediately following a match.
@@ -890,7 +893,7 @@ fn next(&mut self) -> Option<(uint, uint)> {
             if !has_match(&caps) {
                 return None
             } else {
-                (caps.get(0).unwrap(), caps.get(1).unwrap())
+                (caps[0].unwrap(), caps[1].unwrap())
             };
 
         // Don't accept empty matches immediately following a match.
@@ -912,12 +915,12 @@ fn exec(re: &Regex, which: MatchKind, input: &str) -> CaptureLocs {
 fn exec_slice(re: &Regex, which: MatchKind,
               input: &str, s: uint, e: uint) -> CaptureLocs {
     match *re {
-        Dynamic(Dynamic { ref prog, .. }) => vm::run(which, prog, input, s, e),
-        Native(Native { prog, .. }) => prog(which, input, s, e),
+        Dynamic(ExDynamic { ref prog, .. }) => vm::run(which, prog, input, s, e),
+        Native(ExNative { prog, .. }) => prog(which, input, s, e),
     }
 }
 
 #[inline]
 fn has_match(caps: &CaptureLocs) -> bool {
-    caps.len() >= 2 && caps.get(0).is_some() && caps.get(1).is_some()
+    caps.len() >= 2 && caps[0].is_some() && caps[1].is_some()
 }