about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2012-02-14 11:22:31 -0800
committerBrian Anderson <andersrb@gmail.com>2012-02-14 11:22:31 -0800
commitacabd821d2c3503c087b2ce2bd784c14f48cb407 (patch)
tree37a4cc745eb6d2e1da75a5174f1c02c993ee2344
parent0cae213801d0c42c999ed9bb122e61db553b4d5e (diff)
parent69834646d2efd2170236b1f8db3a71c77e378c5b (diff)
Merge pull request #1831 from killerswan/str_fixes
(core::str) changes to find / find_bytes
-rw-r--r--src/comp/back/link.rs3
-rw-r--r--src/comp/driver/driver.rs24
-rw-r--r--src/compiletest/errors.rs8
-rw-r--r--src/compiletest/header.rs21
-rw-r--r--src/compiletest/runtest.rs2
-rw-r--r--src/fuzzer/fuzzer.rs2
-rw-r--r--src/libcore/str.rs140
-rw-r--r--src/libstd/test.rs2
-rw-r--r--src/rustdoc/markdown_pass.rs10
9 files changed, 129 insertions, 83 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index adb9f31f13e..3d345c1a250 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -568,10 +568,11 @@ fn link_binary(sess: session,
     // Converts a library file name into a cc -l argument
     fn unlib(config: @session::config, filename: str) -> str unsafe {
         let rmlib = fn@(filename: str) -> str {
+            let found = str::find_bytes(filename, "lib");
             if config.os == session::os_macos ||
                 (config.os == session::os_linux ||
                  config.os == session::os_freebsd) &&
-                str::find(filename, "lib") == 0 {
+                option::is_some(found) && option::get(found) == 0u {
                 ret str::unsafe::slice_bytes(filename, 3u,
                                str::len_bytes(filename));
             } else { ret filename; }
diff --git a/src/comp/driver/driver.rs b/src/comp/driver/driver.rs
index 52f38afc69a..62cffd97099 100644
--- a/src/comp/driver/driver.rs
+++ b/src/comp/driver/driver.rs
@@ -269,28 +269,28 @@ fn pretty_print_input(sess: session, cfg: ast::crate_cfg, input: str,
 }
 
 fn get_os(triple: str) -> option<session::os> {
-    ret if str::find(triple, "win32") >= 0 ||
-               str::find(triple, "mingw32") >= 0 {
+    ret if str::contains(triple, "win32") ||
+               str::contains(triple, "mingw32") {
             some(session::os_win32)
-        } else if str::find(triple, "darwin") >= 0 {
+        } else if str::contains(triple, "darwin") {
             some(session::os_macos)
-        } else if str::find(triple, "linux") >= 0 {
+        } else if str::contains(triple, "linux") {
             some(session::os_linux)
-        } else if str::find(triple, "freebsd") >= 0 {
+        } else if str::contains(triple, "freebsd") {
             some(session::os_freebsd)
         } else { none };
 }
 
 fn get_arch(triple: str) -> option<session::arch> {
-    ret if str::find(triple, "i386") >= 0 || str::find(triple, "i486") >= 0 ||
-               str::find(triple, "i586") >= 0 ||
-               str::find(triple, "i686") >= 0 ||
-               str::find(triple, "i786") >= 0 {
+    ret if str::contains(triple, "i386") || str::contains(triple, "i486") ||
+               str::contains(triple, "i586") ||
+               str::contains(triple, "i686") ||
+               str::contains(triple, "i786") {
             some(session::arch_x86)
-        } else if str::find(triple, "x86_64") >= 0 {
+        } else if str::contains(triple, "x86_64") {
             some(session::arch_x86_64)
-        } else if str::find(triple, "arm") >= 0 ||
-                      str::find(triple, "xscale") >= 0 {
+        } else if str::contains(triple, "arm") ||
+                      str::contains(triple, "xscale") {
             some(session::arch_arm)
         } else { none };
 }
diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs
index 9d81b6f00e2..f6b32e2fd31 100644
--- a/src/compiletest/errors.rs
+++ b/src/compiletest/errors.rs
@@ -24,9 +24,11 @@ fn load_errors(testfile: str) -> [expected_error] {
 
 fn parse_expected(line_num: uint, line: str) -> [expected_error] unsafe {
     let error_tag = "//!";
-    let idx0 = str::find(line, error_tag);
-    if idx0 < 0 { ret []; }
-    let idx = (idx0 as uint) + str::len_bytes(error_tag);
+    let idx;
+    alt str::find_bytes(line, error_tag) {
+         option::none { ret []; }
+         option::some(nn) { idx = (nn as uint) + str::len_bytes(error_tag); }
+    }
 
     // "//!^^^ kind msg" denotes a message expected
     // three lines above current line:
diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs
index f9c7a7a66e0..a976c5fb98c 100644
--- a/src/compiletest/header.rs
+++ b/src/compiletest/header.rs
@@ -100,18 +100,21 @@ fn parse_pp_exact(line: str, testfile: str) -> option<str> {
 }
 
 fn parse_name_directive(line: str, directive: str) -> bool {
-    str::find(line, directive) >= 0
+    str::contains(line, directive)
 }
 
 fn parse_name_value_directive(line: str,
                               directive: str) -> option<str> unsafe {
     let keycolon = directive + ":";
-    if str::find(line, keycolon) >= 0 {
-        let colon = str::find(line, keycolon) as uint;
-        let value =
-            str::unsafe::slice_bytes(line, colon + str::len_bytes(keycolon),
-                       str::len_bytes(line));
-        #debug("%s: %s", directive,  value);
-        option::some(value)
-    } else { option::none }
+    alt str::find_bytes(line, keycolon) {
+        option::some(colon) {
+            let value =
+                str::unsafe::slice_bytes(line,
+                                         colon + str::len_bytes(keycolon),
+                                         str::len_bytes(line));
+            #debug("%s: %s", directive,  value);
+            option::some(value)
+        }
+        option::none { option::none }
+    }
 }
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index cf5a57c60de..5fb0bca25fa 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -199,7 +199,7 @@ fn check_error_patterns(props: test_props,
     let next_err_idx = 0u;
     let next_err_pat = props.error_patterns[next_err_idx];
     for line: str in str::split_byte(procres.stderr, '\n' as u8) {
-        if str::find(line, next_err_pat) > 0 {
+        if str::contains(line, next_err_pat) {
             #debug("found error pattern %s", next_err_pat);
             next_err_idx += 1u;
             if next_err_idx == vec::len(props.error_patterns) {
diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs
index f6d5f72c367..40d21864021 100644
--- a/src/fuzzer/fuzzer.rs
+++ b/src/fuzzer/fuzzer.rs
@@ -16,7 +16,7 @@ fn write_file(filename: str, content: str) {
 }
 
 fn contains(haystack: str, needle: str) -> bool {
-    str::find(haystack, needle) != -1
+    str::contains(haystack, needle)
 }
 
 fn find_rust_files(&files: [str], path: str) {
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 5b4cc1f77e8..ed2b52cd9d0 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -70,6 +70,7 @@ export
    index,
    rindex,
    find,
+   find_bytes,
    contains,
    starts_with,
    ends_with,
@@ -661,9 +662,10 @@ fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str unsafe {
                      unsafe::slice_bytes(s, len_bytes(from), len_bytes(s)),
                                        from, to);
     } else {
-        let idx = find(s, from);
-        if idx == -1 {
-            ret s;
+        let idx;
+        alt find_bytes(s, from) {
+            option::some(x) { idx = x; }
+            option::none { ret s; }
         }
         let before = unsafe::slice_bytes(s, 0u, idx as uint);
         let after  = unsafe::slice_bytes(s, idx as uint + len_bytes(from),
@@ -872,38 +874,62 @@ fn rindex(ss: str, cc: char) -> option<uint> {
     ret option::none;
 }
 
-/*
-Function: find
+//Function: find_bytes
+//
+// Find the char position of the first instance of one string
+// within another, or return option::none
+//
+// FIXME: Boyer-Moore should be significantly faster
+fn find_bytes(haystack: str, needle: str) -> option<uint> {
+    let haystack_len = len_bytes(haystack);
+    let needle_len   = len_bytes(needle);
 
-Finds the index of the first matching substring.
-Returns -1 if `haystack` does not contain `needle`.
+    if needle_len == 0u { ret option::some(0u); }
+    if needle_len > haystack_len { ret option::none; }
 
-Parameters:
+    fn match_at(haystack: str, needle: str, ii: uint) -> bool {
+        let jj = ii;
+        for c: u8 in needle { if haystack[jj] != c { ret false; } jj += 1u; }
+        ret true;
+    }
 
-haystack - The string to look in
-needle - The string to look for
+    let ii = 0u;
+    while ii <= haystack_len - needle_len {
+        if match_at(haystack, needle, ii) { ret option::some(ii); }
+        ii += 1u;
+    }
 
-Returns:
+    ret option::none;
+}
 
-The index of the first occurance of `needle`, or -1 if not found.
+// Function: find
+//
+// Find the char position of the first instance of one string
+// within another, or return option::none
+fn find(haystack: str, needle: str) -> option<uint> {
+   alt find_bytes(haystack, needle) {
+      option::none { ret option::none; }
+      option::some(nn) { ret option::some(b2c_pos(haystack, nn)); }
+   }
+}
 
-FIXME: return an option<char position uint> instead
-*/
-fn find(haystack: str, needle: str) -> int {
-    let haystack_len: int = len_bytes(haystack) as int;
-    let needle_len: int = len_bytes(needle) as int;
-    if needle_len == 0 { ret 0; }
-    fn match_at(haystack: str, needle: str, i: int) -> bool {
-        let j: int = i;
-        for c: u8 in needle { if haystack[j] != c { ret false; } j += 1; }
-        ret true;
-    }
-    let i: int = 0;
-    while i <= haystack_len - needle_len {
-        if match_at(haystack, needle, i) { ret i; }
-        i += 1;
-    }
-    ret -1;
+// Function: b2c_pos
+//
+// Convert a byte position into a char position
+// within a given string
+fn b2c_pos(ss: str, bpos: uint) -> uint {
+   assert bpos == 0u || bpos < len_bytes(ss);
+
+   let ii = 0u;
+   let cpos = 0u;
+
+   while ii < bpos {
+      let sz = utf8_char_width(ss[ii]);
+      ii += sz;
+      cpos += 1u;
+   }
+
+   ret cpos;
 }
 
 /*
@@ -917,7 +943,7 @@ haystack - The string to look in
 needle - The string to look for
 */
 fn contains(haystack: str, needle: str) -> bool {
-    0 <= find(haystack, needle)
+    option::is_some(find_bytes(haystack, needle))
 }
 
 /*
@@ -930,12 +956,12 @@ Parameters:
 haystack - The string to look in
 needle - The string to look for
 */
-fn starts_with(haystack: str, needle: str) -> bool {
-    let haystack_len: uint = len(haystack);
-    let needle_len: uint = len(needle);
+fn starts_with(haystack: str, needle: str) -> bool unsafe {
+    let haystack_len: uint = len_bytes(haystack);
+    let needle_len: uint = len_bytes(needle);
     if needle_len == 0u { ret true; }
     if needle_len > haystack_len { ret false; }
-    ret eq(substr(haystack, 0u, needle_len), needle);
+    ret eq(unsafe::slice_bytes(haystack, 0u, needle_len), needle);
 }
 
 /*
@@ -1695,25 +1721,39 @@ mod tests {
     }
 
     #[test]
+    fn test_find_bytes() {
+        // byte positions
+        assert (find_bytes("banana", "apple pie") == option::none);
+        assert (find_bytes("", "") == option::some(0u));
+
+        let data = "ประเทศไทย中华Việt Nam";
+        assert (find_bytes(data, "")     == option::some(0u));
+        assert (find_bytes(data, "ประเ") == option::some( 0u));
+        assert (find_bytes(data, "ะเ")   == option::some( 6u));
+        assert (find_bytes(data, "中华") == option::some(27u));
+        assert (find_bytes(data, "ไท华") == option::none);
+    }
+
+    #[test]
     fn test_find() {
-        fn t(haystack: str, needle: str, i: int) {
-            let j: int = find(haystack, needle);
-            log(debug, "searched for " + needle);
-            log(debug, j);
-            assert (i == j);
-        }
-        t("this is a simple", "is a", 5);
-        t("this is a simple", "is z", -1);
-        t("this is a simple", "", 0);
-        t("this is a simple", "simple", 10);
-        t("this", "simple", -1);
+        // char positions
+        assert (find("banana", "apple pie") == option::none);
+        assert (find("", "") == option::some(0u));
 
-        // FIXME: return option<char> position instead
         let data = "ประเทศไทย中华Việt Nam";
-        assert (find(data, "ประเ") ==  0);
-        assert (find(data, "ะเ")   ==  6); // byte position
-        assert (find(data, "中华") ==  27); // byte position
-        assert (find(data, "ไท华") == -1);
+        assert (find(data, "")     == option::some(0u));
+        assert (find(data, "ประเ") == option::some(0u));
+        assert (find(data, "ะเ")   == option::some(2u));
+        assert (find(data, "中华") == option::some(9u));
+        assert (find(data, "ไท华") == option::none);
+    }
+
+    #[test]
+    fn test_b2c_pos() {
+        let data = "ประเทศไทย中华Việt Nam";
+        assert 0u == b2c_pos(data, 0u);
+        assert 2u == b2c_pos(data, 6u);
+        assert 9u == b2c_pos(data, 27u);
     }
 
     #[test]
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
index 8d5ecda2c48..5fd4d59f74d 100644
--- a/src/libstd/test.rs
+++ b/src/libstd/test.rs
@@ -258,7 +258,7 @@ fn filter_tests(opts: test_opts,
 
         fn filter_fn(test: test_desc, filter_str: str) ->
             option<test_desc> {
-            if str::find(test.name, filter_str) >= 0 {
+            if str::contains(test.name, filter_str) {
                 ret option::some(test);
             } else { ret option::none; }
         }
diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs
index c15d6adc7ba..21a7e68cd20 100644
--- a/src/rustdoc/markdown_pass.rs
+++ b/src/rustdoc/markdown_pass.rs
@@ -56,10 +56,10 @@ fn should_write_modules_last() {
          fn d() { }"
     );
 
-    let idx_a = str::find(markdown, "# Module `a`");
-    let idx_b = str::find(markdown, "## Function `b`");
-    let idx_c = str::find(markdown, "# Module `c`");
-    let idx_d = str::find(markdown, "## Function `d`");
+    let idx_a = option::get(str::find_bytes(markdown, "# Module `a`"));
+    let idx_b = option::get(str::find_bytes(markdown, "## Function `b`"));
+    let idx_c = option::get(str::find_bytes(markdown, "# Module `c`"));
+    let idx_d = option::get(str::find_bytes(markdown, "## Function `d`"));
 
     assert idx_b < idx_d;
     assert idx_d < idx_a;
@@ -854,4 +854,4 @@ mod test {
         let markdown = render("mod morp { }");
         assert str::contains(markdown, "Module `morp`\n\n");
     }
-}
\ No newline at end of file
+}