Merge pull request #1336 from erickt/master

misc fixes and library functions
This commit is contained in:
Graydon Hoare 2011-12-19 11:57:44 -08:00
commit 539cfe8a85
8 changed files with 143 additions and 27 deletions

View File

@ -321,7 +321,7 @@ mod write {
*
* There are a few issues to handle:
*
* - Linnkers operate on a flat namespace, so we have to flatten names.
* - Linkers operate on a flat namespace, so we have to flatten names.
* We do this using the C++ namespace-mangling technique. Foo::bar
* symbols and such.
*

View File

@ -46,7 +46,7 @@ syn match rustFloat display contained "\d\+e[-+]\=\d\+[fl]\=\>"
syn match rustCharacter "'[^']*'"
syn case match
syn region rustComment start="/\*" end="\*/"
syn region rustComment start="/\*" end="\*/" contains=rustComment
syn region rustComment start="//" skip="\\$" end="$" keepend
hi def link rustString String
@ -59,5 +59,7 @@ hi def link rustComment Comment
hi def link rustMacro Macro
hi def link rustType Type
let b:current_syntax = "rust"
syn sync minlines=200
syn sync maxlines=500
let b:current_syntax = "rust"

View File

@ -6,11 +6,11 @@ String manipulation.
export eq, lteq, hash, is_empty, is_not_empty, is_whitespace, byte_len,
byte_len_range, index,
rindex, find, starts_with, ends_with, substr, slice, split, split_str,
concat, connect, to_upper, replace, char_slice, trim_left, trim_right,
trim, unshift_char, shift_char, pop_char, push_char, is_utf8,
from_chars, to_chars, char_len, char_len_range, char_at, bytes,
is_ascii, shift_byte, pop_byte,
rindex, find, starts_with, ends_with, substr, slice, split, splitn,
split_str, concat, connect, to_upper, replace, char_slice, trim_left,
trim_right, trim, unshift_char, shift_char, pop_char, push_char,
is_utf8, from_chars, to_chars, char_len, char_len_range, char_at,
bytes, is_ascii, shift_byte, pop_byte,
unsafe_from_byte, unsafe_from_bytes, from_char, char_range_at,
str_from_cstr, sbuf, as_buf, push_byte, utf8_char_width, safe_slice,
contains, iter_chars, loop_chars, loop_chars_sub,
@ -744,6 +744,32 @@ fn split(s: str, sep: u8) -> [str] {
ret v;
}
/*
Function: splitn
Split a string at each occurance of a given separator up to count times.
Returns:
A vector containing all the strings between each occurance of the separator
*/
fn splitn(s: str, sep: u8, count: uint) -> [str] {
let v = [];
let accum = "";
let n = count;
let ends_with_sep: bool = false;
for c in s {
if n > 0u && c == sep {
n -= 1u;
v += [accum];
accum = "";
ends_with_sep = true;
} else { accum += unsafe_from_byte(c); ends_with_sep = false; }
}
if byte_len(accum) != 0u || ends_with_sep { v += [accum]; }
ret v;
}
/*
Function: split_str

View File

@ -300,6 +300,15 @@ fn pop<copy T>(&v: [const T]) -> T {
ret e;
}
/*
Function: push
Append an element to a vector and return it
*/
fn push<copy T>(&v: [T], initval: T) {
grow(v, 1u, initval)
}
// TODO: More.
@ -507,6 +516,24 @@ fn any<T>(v: [T], f: block(T) -> bool) -> bool {
ret false;
}
/*
Function: any2
Return true if a predicate matches any elements in both vectors.
If the vectors contains no elements then false is returned.
*/
fn any2<T, U>(v0: [T], v1: [U], f: block(T, U) -> bool) -> bool {
let v0_len = len(v0);
let v1_len = len(v1);
let i = 0u;
while i < v0_len && i < v1_len {
if f(v0[i], v1[i]) { ret true; };
i += 1u;
}
ret false;
}
/*
Function: all
@ -519,6 +546,21 @@ fn all<T>(v: [T], f: block(T) -> bool) -> bool {
ret true;
}
/*
Function: all2
Return true if a predicate matches all elements in both vectors.
If the vectors are not the same size then false is returned.
*/
fn all2<T, U>(v0: [T], v1: [U], f: block(T, U) -> bool) -> bool {
let v0_len = len(v0);
if v0_len != len(v1) { ret false; }
let i = 0u;
while i < v0_len { if !f(v0[i], v1[i]) { ret false; }; i += 1u; }
ret true;
}
/*
Function: member

View File

@ -149,10 +149,7 @@ fn name_str(nm: name) -> str {
}
fn find_opt(opts: [opt], nm: name) -> option::t<uint> {
let i = 0u;
let l = vec::len::<opt>(opts);
while i < l { if opts[i].name == nm { ret some::<uint>(i); } i += 1u; }
ret none::<uint>;
vec::position_pred(opts, { |opt| opt.name == nm })
}
/*

View File

@ -444,10 +444,11 @@ fn test_unrecognized_option_short() {
fn test_combined() {
let args =
["prog", "free1", "-s", "20", "free2", "--flag", "--long=30", "-f",
"-m", "40", "-m", "50"];
"-m", "40", "-m", "50", "-n", "-A B", "-n", "-60 70"];
let opts =
[opt::optopt("s"), opt::optflag("flag"), opt::reqopt("long"),
opt::optflag("f"), opt::optmulti("m"), opt::optopt("notpresent")];
opt::optflag("f"), opt::optmulti("m"), opt::optmulti("n"),
opt::optopt("notpresent")];
let rs = opt::getopts(args, opts);
alt rs {
ok(m) {
@ -460,6 +461,8 @@ fn test_combined() {
assert (opt::opt_present(m, "f"));
assert (opt::opt_strs(m, "m")[0] == "40");
assert (opt::opt_strs(m, "m")[1] == "50");
assert (opt::opt_strs(m, "n")[0] == "-A B");
assert (opt::opt_strs(m, "n")[1] == "-60 70");
assert (!opt::opt_present(m, "notpresent"));
}
_ { fail; }

View File

@ -41,22 +41,37 @@ fn test_index_and_rindex() {
#[test]
fn test_split() {
fn t(s: str, c: char, i: int, k: str) {
log "splitting: " + s;
log i;
fn t(s: str, c: char, u: [str]) {
log "split: " + s;
let v = str::split(s, c as u8);
log "split to: ";
for z: str in v { log z; }
log "comparing: " + v[i] + " vs. " + k;
assert (str::eq(v[i], k));
log v;
assert (vec::all2(v, u, { |a,b| a == b }));
}
t("abc.hello.there", '.', 0, "abc");
t("abc.hello.there", '.', 1, "hello");
t("abc.hello.there", '.', 2, "there");
t(".hello.there", '.', 0, "");
t(".hello.there", '.', 1, "hello");
t("...hello.there.", '.', 3, "hello");
t("...hello.there.", '.', 5, "");
t("abc.hello.there", '.', ["abc", "hello", "there"]);
t(".hello.there", '.', ["", "hello", "there"]);
t("...hello.there.", '.', ["", "", "", "hello", "there", ""]);
}
#[test]
fn test_splitn() {
fn t(s: str, c: char, n: uint, u: [str]) {
log "splitn: " + s;
let v = str::splitn(s, c as u8, n);
log "split to: ";
log v;
log "comparing vs. ";
log u;
assert (vec::all2(v, u, { |a,b| a == b }));
}
t("abc.hello.there", '.', 0u, ["abc.hello.there"]);
t("abc.hello.there", '.', 1u, ["abc", "hello.there"]);
t("abc.hello.there", '.', 2u, ["abc", "hello", "there"]);
t("abc.hello.there", '.', 3u, ["abc", "hello", "there"]);
t(".hello.there", '.', 0u, [".hello.there"]);
t(".hello.there", '.', 1u, ["", "hello.there"]);
t("...hello.there.", '.', 3u, ["", "", "", "hello.there."]);
t("...hello.there.", '.', 5u, ["", "", "", "hello", "there", ""]);
}
#[test]

View File

@ -16,6 +16,8 @@ pure fn is_three(&&n: uint) -> bool { ret n == 3u; }
pure fn is_odd(&&n: uint) -> bool { ret n % 2u == 1u; }
pure fn is_equal(&&x: uint, &&y:uint) -> bool { ret x == y; }
fn square_if_odd(&&n: uint) -> option::t<uint> {
ret if n % 2u == 1u { some(n * n) } else { none };
}
@ -168,6 +170,21 @@ fn test_pop() {
assert (e == 5);
}
#[test]
fn test_push() {
// Test on-stack push().
let v = [];
vec::push(v, 1);
assert (vec::len(v) == 1u);
assert (v[0] == 1);
// Test on-heap push().
vec::push(v, 2);
assert (vec::len(v) == 2u);
assert (v[0] == 1);
assert (v[1] == 2);
}
#[test]
fn test_grow() {
// Test on-stack grow().
@ -401,6 +418,20 @@ fn test_any_and_all() {
assert (!vec::all([3u, 3u, 0u, 1u, 2u], is_three));
}
#[test]
fn test_any2_and_all2() {
assert (vec::any2([2u, 4u, 6u], [2u, 4u, 6u], is_equal));
assert (vec::any2([1u, 2u, 3u], [4u, 5u, 3u], is_equal));
assert (!vec::any2([1u, 2u, 3u], [4u, 5u, 6u], is_equal));
assert (vec::any2([2u, 4u, 6u], [2u, 4u], is_equal));
assert (vec::all2([2u, 4u, 6u], [2u, 4u, 6u], is_equal));
assert (!vec::all2([1u, 2u, 3u], [4u, 5u, 3u], is_equal));
assert (!vec::all2([1u, 2u, 3u], [4u, 5u, 6u], is_equal));
assert (!vec::all2([2u, 4u, 6u], [2u, 4u], is_equal));
}
#[test]
fn test_zip_unzip() {
let v1 = [1, 2, 3];