diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 83df9b7c00f..fcdd8fdd571 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -218,7 +218,7 @@ fn write(&self) -> bool { fn write_escaped_slice(&self, slice: &str) { self.writer.write_char('"'); - for str::chars_each(slice) |ch| { + for slice.each_char |ch| { self.writer.write_escaped_char(ch); } self.writer.write_char('"'); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 3d591af6d3c..748cea50e90 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -596,20 +596,20 @@ pub fn unshift_char(s: &mut ~str, ch: char) { /// Levenshtein Distance between two strings pub fn levdistance(s: &str, t: &str) -> uint { - let slen = str::len(s); - let tlen = str::len(t); + let slen = s.len(); + let tlen = s.len(); if slen == 0 { return tlen; } if tlen == 0 { return slen; } let mut dcol = vec::from_fn(tlen + 1, |x| x); - for str::each_chari(s) |i, sc| { + for s.each_chari |i, sc| { let mut current = i; dcol[0] = current + 1; - for str::each_chari(t) |j, tc| { + for s.each_chari |j, tc| { let mut next = dcol[j + 1]; @@ -933,37 +933,44 @@ impl Equiv<~str> for &'self str { let mut result = ~""; unsafe { reserve(&mut result, len(ss)); - for chars_each(ss) |cc| { + for ss.each_char |cc| { str::push_char(&mut result, ff(cc)); } } result } -/// Iterate over the bytes in a string -pub pure fn bytes_each(ss: &str, it: &fn(u8) -> bool) { - let mut pos = 0u; - let len = len(ss); - - while (pos < len) { - if !it(ss[pos]) { return; } - pos += 1u; - } -} - /// Iterate over the bytes in a string #[inline(always)] pub pure fn each(s: &str, it: &fn(u8) -> bool) { - eachi(s, |_i, b| it(b) ) + eachi(s, |_i, b| it(b)) } /// Iterate over the bytes in a string, with indices #[inline(always)] pub pure fn eachi(s: &str, it: &fn(uint, u8) -> bool) { - let mut i = 0u, l = len(s); - while (i < l) { - if !it(i, s[i]) { break; } - i += 1u; + let mut pos = 0; + let len = s.len(); + + while pos < len { + if !it(pos, s[pos]) { break; } + pos += 1; + } +} + +/// Iterate over the bytes in a string in reverse +#[inline(always)] +pub pure fn each_reverse(s: &str, it: &fn(u8) -> bool) { + eachi_reverse(s, |_i, b| it(b) ) +} + +/// Iterate over the bytes in a string in reverse, with indices +#[inline(always)] +pub pure fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) { + let mut pos = s.len(); + while pos > 0 { + pos -= 1; + if !it(pos, s[pos]) { break; } } } @@ -976,8 +983,9 @@ impl Equiv<~str> for &'self str { /// Iterates over the chars in a string, with indices #[inline(always)] pub pure fn each_chari(s: &str, it: &fn(uint, char) -> bool) { - let mut pos = 0u, ch_pos = 0u; - let len = len(s); + let mut pos = 0; + let mut ch_pos = 0u; + let len = s.len(); while pos < len { let CharRange {ch, next} = char_range_at(s, pos); pos = next; @@ -986,14 +994,25 @@ impl Equiv<~str> for &'self str { } } -/// Iterate over the characters in a string -pub pure fn chars_each(s: &str, it: &fn(char) -> bool) { - let mut pos = 0u; - let len = len(s); - while (pos < len) { - let CharRange {ch, next} = char_range_at(s, pos); +/// Iterates over the chars in a string in reverse +#[inline(always)] +pub pure fn each_char_reverse(s: &str, it: &fn(char) -> bool) { + let mut pos = 0; + let len = s.char_len(); + while pos > 0 { + let CharRange {ch, next} = char_range_at_reverse(s, pos); pos = next; - if !it(ch) { return; } + if !it(ch) { break; } + } +} + +// Iterates over the chars in a string in reverse, with indices +#[inline(always)] +pub pure fn each_chari_reverse(s: &str, it: &fn(uint, char) -> bool) { + let mut ch_pos = s.char_len(); + for s.each_char_reverse |ch| { + ch_pos -= 1; + if !it(ch_pos, ch) { break; } } } @@ -1573,9 +1592,9 @@ impl Equiv<~str> for &'self str { /// Converts to a vector of `u16` encoded as UTF-16 pub pure fn to_utf16(s: &str) -> ~[u16] { let mut u = ~[]; - for chars_each(s) |cch| { + for s.each_char |ch| { // Arithmetic with u32 literals is easier on the eyes than chars. - let mut ch = cch as u32; + let mut ch = ch as u32; unsafe { if (ch & 0xFFFF_u32) == ch { @@ -1769,7 +1788,7 @@ impl Equiv<~str> for &'self str { return CharRange {ch: val as char, next: i}; } -/// Pluck a character out of a string +/// Plucks the `n`th character from the beginning of a string pub pure fn char_at(s: &str, i: uint) -> char { return char_range_at(s, i).ch; } @@ -1799,6 +1818,11 @@ pub struct CharRange { return CharRange {ch:ch, next:prev}; } +/// Plucks the `n`th character from the end of a string +pub pure fn char_at_reverse(s: &str, i: uint) -> char { + char_range_at_reverse(s, i).ch +} + /** * Loop through a substring, char by char * @@ -2022,7 +2046,7 @@ pub fn reserve_at_least(s: &mut ~str, n: uint) { let mut out: ~str = ~""; unsafe { reserve_at_least(&mut out, str::len(s)); - for chars_each(s) |c| { + for s.each_char |c| { push_str(&mut out, char::escape_default(c)); } } @@ -2034,7 +2058,7 @@ pub fn reserve_at_least(s: &mut ~str, n: uint) { let mut out: ~str = ~""; unsafe { reserve_at_least(&mut out, str::len(s)); - for chars_each(s) |c| { + for s.each_char |c| { push_str(&mut out, char::escape_unicode(c)); } } @@ -2251,13 +2275,18 @@ pub trait StrSlice { pure fn contains_char(&self, needle: char) -> bool; pure fn each(&self, it: &fn(u8) -> bool); pure fn eachi(&self, it: &fn(uint, u8) -> bool); + pure fn each_reverse(&self, it: &fn(u8) -> bool); + pure fn eachi_reverse(&self, it: &fn(uint, u8) -> bool); pure fn each_char(&self, it: &fn(char) -> bool); pure fn each_chari(&self, it: &fn(uint, char) -> bool); + pure fn each_char_reverse(&self, it: &fn(char) -> bool); + pure fn each_chari_reverse(&self, it: &fn(uint, char) -> bool); pure fn ends_with(&self, needle: &str) -> bool; pure fn is_empty(&self) -> bool; pure fn is_whitespace(&self) -> bool; pure fn is_alphanumeric(&self) -> bool; pure fn len(&self) -> uint; + pure fn char_len(&self) -> uint; pure fn slice(&self, begin: uint, end: uint) -> ~str; pure fn split(&self, sepfn: &fn(char) -> bool) -> ~[~str]; pure fn split_char(&self, sep: char) -> ~[~str]; @@ -2274,6 +2303,7 @@ pub trait StrSlice { pure fn to_owned(&self) -> ~str; pure fn to_managed(&self) -> @str; pure fn char_at(&self, i: uint) -> char; + pure fn char_at_reverse(&self, i: uint) -> char; fn to_bytes(&self) -> ~[u8]; } @@ -2307,6 +2337,16 @@ impl StrSlice for &'self str { /// Iterate over the bytes in a string, with indices #[inline] pure fn eachi(&self, it: &fn(uint, u8) -> bool) { eachi(*self, it) } + /// Iterate over the bytes in a string + #[inline] + pure fn each_reverse(&self, it: &fn(u8) -> bool) { + each_reverse(*self, it) + } + /// Iterate over the bytes in a string, with indices + #[inline] + pure fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) { + eachi_reverse(*self, it) + } /// Iterate over the chars in a string #[inline] pure fn each_char(&self, it: &fn(char) -> bool) { each_char(*self, it) } @@ -2315,6 +2355,17 @@ impl StrSlice for &'self str { pure fn each_chari(&self, it: &fn(uint, char) -> bool) { each_chari(*self, it) } + /// Iterate over the chars in a string in reverse + #[inline] + pure fn each_char_reverse(&self, it: &fn(char) -> bool) { + each_char_reverse(*self, it) + } + /// Iterate over the chars in a string in reverse, with indices from the + /// end + #[inline] + pure fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) { + each_chari_reverse(*self, it) + } /// Returns true if one string ends with another #[inline] pure fn ends_with(&self, needle: &str) -> bool { @@ -2337,9 +2388,12 @@ impl StrSlice for &'self str { */ #[inline] pure fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } - #[inline] /// Returns the size in bytes not counting the null terminator + #[inline] pure fn len(&self) -> uint { len(*self) } + /// Returns the number of characters that a string holds + #[inline] + pure fn char_len(&self) -> uint { char_len(*self) } /** * Returns a slice of the given string from the byte range * [`begin`..`end`) @@ -2419,6 +2473,11 @@ impl StrSlice for &'self str { #[inline] pure fn char_at(&self, i: uint) -> char { char_at(*self, i) } + #[inline] + pure fn char_at_reverse(&self, i: uint) -> char { + char_at_reverse(*self, i) + } + fn to_bytes(&self) -> ~[u8] { to_bytes(*self) } } @@ -3234,41 +3293,6 @@ fn test_contains_char() { fail_unless!(!contains_char(~"", 'a')); } - #[test] - fn test_chars_each() { - let mut i = 0; - for chars_each(~"x\u03c0y") |ch| { - match i { - 0 => fail_unless!(ch == 'x'), - 1 => fail_unless!(ch == '\u03c0'), - 2 => fail_unless!(ch == 'y'), - _ => fail!(~"test_chars_each failed") - } - i += 1; - } - - chars_each(~"", |_ch| fail!() ); // should not fail - } - - #[test] - fn test_bytes_each() { - let mut i = 0; - - for bytes_each(~"xyz") |bb| { - match i { - 0 => fail_unless!(bb == 'x' as u8), - 1 => fail_unless!(bb == 'y' as u8), - 2 => fail_unless!(bb == 'z' as u8), - _ => fail!(~"test_bytes_each failed") - } - i += 1; - } - - for bytes_each(~"") |bb| { - fail_unless!(bb == 0u8); - } - } - #[test] fn test_split_char_each() { let data = ~"\nMary had a little lamb\nLittle lamb\n"; @@ -3427,16 +3451,167 @@ fn test_utf16() { } #[test] - fn test_each_char() { - let s = ~"abc"; - let mut found_b = false; - for each_char(s) |ch| { - if ch == 'b' { - found_b = true; - break; - } + fn test_char_at() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for v.each |ch| { + fail_unless!(s.char_at(pos) == *ch); + pos += from_char(*ch).len(); + } + } + + #[test] + fn test_char_at_reverse() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = s.len(); + for v.each_reverse |ch| { + fail_unless!(s.char_at_reverse(pos) == *ch); + pos -= from_char(*ch).len(); + } + } + + #[test] + fn test_each() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = 0; + + for s.each |b| { + fail_unless!(b == v[pos]); + pos += 1; + } + } + + #[test] + fn test_each_empty() { + for "".each |b| { + fail_unless!(b == 0u8); + } + } + + #[test] + fn test_eachi() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = 0; + + for s.eachi |i, b| { + fail_unless!(pos == i); + fail_unless!(b == v[pos]); + pos += 1; + } + } + + #[test] + fn test_eachi_empty() { + for "".eachi |i, b| { + fail_unless!(i == 0); + fail_unless!(b == 0); + } + } + + #[test] + fn test_each_reverse() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = v.len(); + + for s.each_reverse |b| { + pos -= 1; + fail_unless!(b == v[pos]); + } + } + + #[test] + fn test_each_empty_reverse() { + for "".each_reverse |b| { + fail_unless!(b == 0u8); + } + } + + #[test] + fn test_eachi_reverse() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = v.len(); + + for s.eachi_reverse |i, b| { + pos -= 1; + fail_unless!(pos == i); + fail_unless!(b == v[pos]); + } + } + + #[test] + fn test_eachi_reverse_empty() { + for "".eachi_reverse |i, b| { + fail_unless!(i == 0); + fail_unless!(b == 0); + } + } + + #[test] + fn test_each_char() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for s.each_char |ch| { + fail_unless!(ch == v[pos]); + pos += 1; + } + } + + #[test] + fn test_each_chari() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for s.each_chari |i, ch| { + fail_unless!(pos == i); + fail_unless!(ch == v[pos]); + pos += 1; + } + } + + #[test] + fn test_each_char_reverse() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for s.each_char_reverse |ch| { + fail_unless!(ch == v[pos]); + pos += 1; + } + } + + #[test] + fn test_each_chari_reverse() { + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = v.len(); + for s.each_chari_reverse |i, ch| { + pos -= 1; + fail_unless!(pos == i); + fail_unless!(ch == v[pos]); } - fail_unless!(found_b); } #[test] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index dc220eaed1b..e41aefc94e5 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1005,7 +1005,7 @@ pub fn retain(v: &mut ~[T], f: &pure fn(t: &T) -> bool) { */ pub pure fn foldr(v: &[T], z: U, p: &fn(t: &T, u: U) -> U) -> U { let mut accum = z; - for rev_each(v) |elt| { + for v.each_reverse |elt| { accum = p(elt, accum); } accum @@ -1411,8 +1411,8 @@ pub fn each_mut(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) { * Return true to continue, false to break. */ #[inline(always)] -pub pure fn rev_each(v: &'r [T], blk: &fn(v: &'r T) -> bool) { - rev_eachi(v, |_i, v| blk(v)) +pub pure fn each_reverse(v: &'r [T], blk: &fn(v: &'r T) -> bool) { + eachi_reverse(v, |_i, v| blk(v)) } /** @@ -1421,7 +1421,7 @@ pub fn each_mut(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) { * Return true to continue, false to break. */ #[inline(always)] -pub pure fn rev_eachi(v: &'r [T], blk: &fn(i: uint, v: &'r T) -> bool) { +pub pure fn eachi_reverse(v: &'r [T], blk: &fn(i: uint, v: &'r T) -> bool) { let mut i = v.len(); while i > 0 { i -= 1; @@ -1736,6 +1736,8 @@ pub trait ImmutableVector { pure fn initn(&self, n: uint) -> &'self [T]; pure fn last(&self) -> &'self T; pure fn last_opt(&self) -> Option<&'self T>; + pure fn each_reverse(&self, blk: &fn(&T) -> bool); + pure fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool); pure fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U; pure fn map(&self, f: &fn(t: &T) -> U) -> ~[U]; pure fn mapi(&self, f: &fn(uint, t: &T) -> U) -> ~[U]; @@ -1785,6 +1787,18 @@ impl ImmutableVector for &'self [T] { #[inline] pure fn last_opt(&self) -> Option<&'self T> { last_opt(*self) } + /// Iterates over a vector's elements in reverse. + #[inline] + pure fn each_reverse(&self, blk: &fn(&T) -> bool) { + each_reverse(*self, blk) + } + + /// Iterates over a vector's elements and indices in reverse. + #[inline] + pure fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) { + eachi_reverse(*self, blk) + } + /// Reduce a vector from right to left #[inline] pure fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U { @@ -3131,16 +3145,17 @@ fn test_iteri() { } #[test] - fn test_reach_empty() { - for rev_each::(~[]) |_v| { + fn test_each_reverse_empty() { + let v: ~[int] = ~[]; + for v.each_reverse |_v| { fail!(); // should never execute } } #[test] - fn test_reach_nonempty() { + fn test_each_reverse_nonempty() { let mut i = 0; - for rev_each(~[1, 2, 3]) |v| { + for each_reverse(~[1, 2, 3]) |v| { if i == 0 { fail_unless!(*v == 3); } i += *v } @@ -3148,9 +3163,9 @@ fn test_reach_nonempty() { } #[test] - fn test_reachi() { + fn test_eachi_reverse() { let mut i = 0; - for rev_eachi(~[0, 1, 2]) |j, v| { + for eachi_reverse(~[0, 1, 2]) |j, v| { if i == 0 { fail_unless!(*v == 2); } fail_unless!(j == *v as uint); i += *v; @@ -3158,6 +3173,14 @@ fn test_reachi() { fail_unless!(i == 3); } + #[test] + fn test_eachi_reverse_empty() { + let v: ~[int] = ~[]; + for v.eachi_reverse |_i, _v| { + fail!(); // should never execute + } + } + #[test] fn test_each_permutation() { let mut results: ~[~[int]]; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 9965a4a6fcd..d953c3bd033 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -656,7 +656,7 @@ pub fn get_symbol_hash(ccx: @CrateContext, t: ty::t) -> @str { // gas doesn't! pub fn sanitize(s: &str) -> ~str { let mut result = ~""; - for str::chars_each(s) |c| { + for str::each_char(s) |c| { match c { '@' => result += ~"_sbox_", '~' => result += ~"_ubox_", diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index fad8f39cdf3..9346872f949 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1264,7 +1264,7 @@ pub fn trans_block_cleanups_(bcx: block, bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0; if bcx.unreachable && !no_lpads { return bcx; } let mut bcx = bcx; - for vec::rev_each(cleanups) |cu| { + for cleanups.each_reverse |cu| { match *cu { clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => { // Some types don't need to be cleaned up during diff --git a/src/libstd/bigint.rs b/src/libstd/bigint.rs index e128859bb7d..cdc65de4987 100644 --- a/src/libstd/bigint.rs +++ b/src/libstd/bigint.rs @@ -324,7 +324,7 @@ pub impl BigUint { if s_len < o_len { return -1; } if s_len > o_len { return 1; } - for vec::rev_eachi(self.data) |i, elm| { + for self.data.eachi_reverse |i, elm| { match (*elm, other.data[i]) { (l, r) if l < r => return -1, (l, r) if l > r => return 1, @@ -387,7 +387,7 @@ pub impl BigUint { let bn = *b.data.last(); let mut d = ~[]; let mut carry = 0; - for vec::rev_each(an) |elt| { + for an.each_reverse |elt| { let ai = BigDigit::to_uint(carry, *elt); let di = ai / (bn as uint); fail_unless!(di < BigDigit::base); @@ -499,7 +499,7 @@ pub impl BigUint { let mut borrow = 0; let mut shifted = ~[]; - for vec::rev_each(self.data) |elem| { + for self.data.each_reverse |elem| { shifted = ~[(*elem >> n_bits) | borrow] + shifted; borrow = *elem << (uint::bits - n_bits); } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index f2f37604fb5..7503f28e848 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -14,20 +14,14 @@ //! json serialization +use core::prelude::*; +use core::io::{WriterUtil, ReaderUtil}; +use core::hashmap::linear::LinearMap; + use serialize::Encodable; use serialize; use sort::Sort; -use core::char; -use core::cmp::{Eq, Ord}; -use core::float; -use core::io::{WriterUtil, ReaderUtil}; -use core::io; -use core::prelude::*; -use core::hashmap::linear::LinearMap; -use core::str; -use core::to_str; - /// Represents a json value pub enum Json { Number(float), @@ -49,7 +43,7 @@ pub struct Error { fn escape_str(s: &str) -> ~str { let mut escaped = ~"\""; - for str::chars_each(s) |c| { + for str::each_char(s) |c| { match c { '"' => escaped += ~"\\\"", '\\' => escaped += ~"\\\\",