提交 a54476b0 编写于 作者: E Erick Tryzelaar

Merge remote-tracking branch 'remotes/origin/master' into remove-str-trailing-nulls

......@@ -297,7 +297,7 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/librustc/, \
LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rs
LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \
*.rs */*.rs */*/*.rs))
*.rs */*.rs */*/*.rs */*/*/*.rs))
DRIVER_CRATE := $(S)src/driver/driver.rs
......
......@@ -544,7 +544,7 @@ an intermediate generation has already exited:
~~~
# use std::task;
# fn sleep_forever() { loop { task::yield() } }
# fn wait_for_a_while() { do 1000.times { task::yield() } }
# fn wait_for_a_while() { for _ in range(0, 1000u) { task::yield() } }
# do task::try::<int> {
do task::spawn_supervised {
do task::spawn_supervised {
......@@ -563,7 +563,7 @@ other at all, using `task::spawn_unlinked` for _isolated failure_.
~~~
# use std::task;
# fn random() -> uint { 100 }
# fn sleep_for(i: uint) { do i.times { task::yield() } }
# fn sleep_for(i: uint) { for _ in range(0, i) { task::yield() } }
# do task::try::<()> {
let (time1, time2) = (random(), random());
do task::spawn_unlinked {
......
......@@ -1894,7 +1894,7 @@ struct TimeBomb {
impl Drop for TimeBomb {
fn drop(&self) {
do self.explosivity.times {
for _ in range(0, self.explosivity) {
println("blam!");
}
}
......
......@@ -9,6 +9,7 @@
// except according to those terms.
//! Base64 binary-to-text encoding
use std::str;
/// Available encoding character sets
pub enum CharacterSet {
......@@ -40,21 +41,13 @@ pub struct Config {
pub static MIME: Config =
Config {char_set: Standard, pad: true, line_length: Some(76)};
static STANDARD_CHARS: [char, ..64] = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];
static URLSAFE_CHARS: [char, ..64] = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
];
static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789+/");
static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789-_");
/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
......@@ -80,12 +73,12 @@ impl<'self> ToBase64 for &'self [u8] {
* ~~~
*/
fn to_base64(&self, config: Config) -> ~str {
let chars = match config.char_set {
let bytes = match config.char_set {
Standard => STANDARD_CHARS,
UrlSafe => URLSAFE_CHARS
};
let mut s = ~"";
let mut v: ~[u8] = ~[];
let mut i = 0;
let mut cur_length = 0;
let len = self.len();
......@@ -93,7 +86,8 @@ fn to_base64(&self, config: Config) -> ~str {
match config.line_length {
Some(line_length) =>
if cur_length >= line_length {
s.push_str("\r\n");
v.push('\r' as u8);
v.push('\n' as u8);
cur_length = 0;
},
None => ()
......@@ -104,10 +98,10 @@ fn to_base64(&self, config: Config) -> ~str {
(self[i + 2] as u32);
// This 24-bit number gets separated into four 6-bit numbers.
s.push_char(chars[(n >> 18) & 63]);
s.push_char(chars[(n >> 12) & 63]);
s.push_char(chars[(n >> 6 ) & 63]);
s.push_char(chars[n & 63]);
v.push(bytes[(n >> 18) & 63]);
v.push(bytes[(n >> 12) & 63]);
v.push(bytes[(n >> 6 ) & 63]);
v.push(bytes[n & 63]);
cur_length += 4;
i += 3;
......@@ -117,7 +111,8 @@ fn to_base64(&self, config: Config) -> ~str {
match config.line_length {
Some(line_length) =>
if cur_length >= line_length {
s.push_str("\r\n");
v.push('\r' as u8);
v.push('\n' as u8);
},
None => ()
}
......@@ -129,48 +124,29 @@ fn to_base64(&self, config: Config) -> ~str {
0 => (),
1 => {
let n = (self[i] as u32) << 16;
s.push_char(chars[(n >> 18) & 63]);
s.push_char(chars[(n >> 12) & 63]);
v.push(bytes[(n >> 18) & 63]);
v.push(bytes[(n >> 12) & 63]);
if config.pad {
s.push_str("==");
v.push('=' as u8);
v.push('=' as u8);
}
}
2 => {
let n = (self[i] as u32) << 16 |
(self[i + 1u] as u32) << 8;
s.push_char(chars[(n >> 18) & 63]);
s.push_char(chars[(n >> 12) & 63]);
s.push_char(chars[(n >> 6 ) & 63]);
v.push(bytes[(n >> 18) & 63]);
v.push(bytes[(n >> 12) & 63]);
v.push(bytes[(n >> 6 ) & 63]);
if config.pad {
s.push_char('=');
v.push('=' as u8);
}
}
_ => fail!("Algebra is broken, please alert the math police")
}
s
}
}
impl<'self> ToBase64 for &'self str {
/**
* Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
*
*
* # Example
*
* ~~~ {.rust}
* extern mod extra;
* use extra::base64::{ToBase64, standard};
*
* fn main () {
* let str = "Hello, World".to_base64(standard);
* printfln!("%s", str);
* }
* ~~~
*
*/
fn to_base64(&self, config: Config) -> ~str {
self.as_bytes().to_base64(config)
unsafe {
str::raw::from_bytes_owned(v)
}
}
}
......@@ -181,22 +157,31 @@ pub trait FromBase64 {
fn from_base64(&self) -> Result<~[u8], ~str>;
}
impl<'self> FromBase64 for &'self [u8] {
impl<'self> FromBase64 for &'self str {
/**
* Convert base64 `u8` vector into u8 byte values.
* Every 4 encoded characters is converted into 3 octets, modulo padding.
* Convert any base64 encoded string (literal, `@`, `&`, or `~`)
* to the byte values it encodes.
*
* You can use the `from_bytes` function in `std::str`
* to turn a `[u8]` into a string with characters corresponding to those
* values.
*
* # Example
*
* This converts a string literal to base64 and back.
*
* ~~~ {.rust}
* extern mod extra;
* use extra::base64::{ToBase64, FromBase64, standard};
* use std::str;
*
* fn main () {
* let str = [52,32].to_base64(standard);
* printfln!("%s", str);
* let bytes = str.from_base64();
* let hello_str = "Hello, World".to_base64(standard);
* printfln!("%s", hello_str);
* let bytes = hello_str.from_base64();
* printfln!("%?", bytes);
* let result_str = str::from_bytes(bytes);
* printfln!("%s", result_str);
* }
* ~~~
*/
......@@ -205,12 +190,11 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
let mut buf: u32 = 0;
let mut modulus = 0;
let mut it = self.iter();
for &byte in it {
let ch = byte as char;
let mut it = self.byte_iter().enumerate();
for (idx, byte) in it {
let val = byte as u32;
match ch {
match byte as char {
'A'..'Z' => buf |= val - 0x41,
'a'..'z' => buf |= val - 0x47,
'0'..'9' => buf |= val + 0x04,
......@@ -218,7 +202,8 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
'/'|'_' => buf |= 0x3F,
'\r'|'\n' => loop,
'=' => break,
_ => return Err(~"Invalid Base64 character")
_ => return Err(fmt!("Invalid character '%c' at position %u",
self.char_at(idx), idx))
}
buf <<= 6;
......@@ -231,8 +216,11 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
}
}
if !it.all(|&byte| {byte as char == '='}) {
return Err(~"Invalid Base64 character");
for (idx, byte) in it {
if (byte as char) != '=' {
return Err(fmt!("Invalid character '%c' at position %u",
self.char_at(idx), idx));
}
}
match modulus {
......@@ -251,39 +239,6 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
}
}
impl<'self> FromBase64 for &'self str {
/**
* Convert any base64 encoded string (literal, `@`, `&`, or `~`)
* to the byte values it encodes.
*
* You can use the `from_bytes` function in `std::str`
* to turn a `[u8]` into a string with characters corresponding to those
* values.
*
* # Example
*
* This converts a string literal to base64 and back.
*
* ~~~ {.rust}
* extern mod extra;
* use extra::base64::{ToBase64, FromBase64, standard};
* use std::str;
*
* fn main () {
* let hello_str = "Hello, World".to_base64(standard);
* printfln!("%s", hello_str);
* let bytes = hello_str.from_base64();
* printfln!("%?", bytes);
* let result_str = str::from_bytes(bytes);
* printfln!("%s", result_str);
* }
* ~~~
*/
fn from_base64(&self) -> Result<~[u8], ~str> {
self.as_bytes().from_base64()
}
}
#[cfg(test)]
mod test {
use test::BenchHarness;
......@@ -291,27 +246,28 @@ mod test {
#[test]
fn test_to_base64_basic() {
assert_eq!("".to_base64(STANDARD), ~"");
assert_eq!("f".to_base64(STANDARD), ~"Zg==");
assert_eq!("fo".to_base64(STANDARD), ~"Zm8=");
assert_eq!("foo".to_base64(STANDARD), ~"Zm9v");
assert_eq!("foob".to_base64(STANDARD), ~"Zm9vYg==");
assert_eq!("fooba".to_base64(STANDARD), ~"Zm9vYmE=");
assert_eq!("foobar".to_base64(STANDARD), ~"Zm9vYmFy");
assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
}
#[test]
fn test_to_base64_line_break() {
assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
.contains("\r\n"));
assert_eq!("foobar".to_base64(Config {line_length: Some(4), ..STANDARD}),
assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
..STANDARD}),
~"Zm9v\r\nYmFy");
}
#[test]
fn test_to_base64_padding() {
assert_eq!("f".to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
assert_eq!("fo".to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
}
#[test]
......@@ -345,7 +301,7 @@ fn test_from_base64_urlsafe() {
#[test]
fn test_from_base64_invalid_char() {
assert!("Zm$=".from_base64().is_err())
assert!("Zg==$".from_base64().is_err());
assert!("Zg==$".from_base64().is_err());
}
#[test]
......@@ -369,20 +325,20 @@ fn test_base64_random() {
}
#[bench]
pub fn to_base64(bh: & mut BenchHarness) {
pub fn bench_to_base64(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
do bh.iter {
s.to_base64(STANDARD);
s.as_bytes().to_base64(STANDARD);
}
bh.bytes = s.len() as u64;
}
#[bench]
pub fn from_base64(bh: & mut BenchHarness) {
pub fn bench_from_base64(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
let b = s.to_base64(STANDARD);
let b = s.as_bytes().to_base64(STANDARD);
do bh.iter {
b.from_base64();
}
......
......@@ -102,6 +102,7 @@
pub mod semver;
pub mod fileinput;
pub mod flate;
pub mod hex;
#[cfg(unicode)]
mod unicode;
......
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Hex binary-to-text encoding
use std::str;
use std::vec;
/// A trait for converting a value to hexadecimal encoding
pub trait ToHex {
/// Converts the value of `self` to a hex value, returning the owned
/// string.
fn to_hex(&self) -> ~str;
}
static CHARS: &'static[u8] = bytes!("0123456789abcdef");
impl<'self> ToHex for &'self [u8] {
/**
* Turn a vector of `u8` bytes into a hexadecimal string.
*
* # Example
*
* ~~~ {.rust}
* extern mod extra;
* use extra::hex::ToHex;
*
* fn main () {
* let str = [52,32].to_hex();
* printfln!("%s", str);
* }
* ~~~
*/
fn to_hex(&self) -> ~str {
let mut v = vec::with_capacity(self.len() * 2);
for &byte in self.iter() {
v.push(CHARS[byte >> 4]);
v.push(CHARS[byte & 0xf]);
}
unsafe {
str::raw::from_bytes_owned(v)
}
}
}
/// A trait for converting hexadecimal encoded values
pub trait FromHex {
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
/// into an owned vector of bytes, returning the vector.
fn from_hex(&self) -> Result<~[u8], ~str>;
}
impl<'self> FromHex for &'self str {
/**
* Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
* to the byte values it encodes.
*
* You can use the `from_bytes` function in `std::str`
* to turn a `[u8]` into a string with characters corresponding to those
* values.
*
* # Example
*
* This converts a string literal to hexadecimal and back.
*
* ~~~ {.rust}
* extern mod extra;
* use extra::hex::{FromHex, ToHex};
* use std::str;
*
* fn main () {
* let hello_str = "Hello, World".to_hex();
* printfln!("%s", hello_str);
* let bytes = hello_str.from_hex().unwrap();
* printfln!("%?", bytes);
* let result_str = str::from_bytes(bytes);
* printfln!("%s", result_str);
* }
* ~~~
*/
fn from_hex(&self) -> Result<~[u8], ~str> {
// This may be an overestimate if there is any whitespace
let mut b = vec::with_capacity(self.len() / 2);
let mut modulus = 0;
let mut buf = 0u8;
for (idx, byte) in self.byte_iter().enumerate() {
buf <<= 4;
match byte as char {
'A'..'F' => buf |= byte - ('A' as u8) + 10,
'a'..'f' => buf |= byte - ('a' as u8) + 10,
'0'..'9' => buf |= byte - ('0' as u8),
' '|'\r'|'\n'|'\t' => {
buf >>= 4;
loop
}
_ => return Err(fmt!("Invalid character '%c' at position %u",
self.char_at(idx), idx))
}
modulus += 1;
if modulus == 2 {
modulus = 0;
b.push(buf);
}
}
match modulus {
0 => Ok(b),
_ => Err(~"Invalid input length")
}
}
}
#[cfg(test)]
mod tests {
use test::BenchHarness;
use hex::*;
#[test]
pub fn test_to_hex() {
assert_eq!("foobar".as_bytes().to_hex(), ~"666f6f626172");
}
#[test]
pub fn test_from_hex_okay() {
assert_eq!("666f6f626172".from_hex().unwrap(),
"foobar".as_bytes().to_owned());
assert_eq!("666F6F626172".from_hex().unwrap(),
"foobar".as_bytes().to_owned());
}
#[test]
pub fn test_from_hex_odd_len() {
assert!("666".from_hex().is_err());
assert!("66 6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_invalid_char() {
assert!("66y6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_ignores_whitespace() {
assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(),
"foobar".as_bytes().to_owned());
}
#[test]
pub fn test_to_hex_all_bytes() {
for i in range(0, 256) {
assert_eq!([i as u8].to_hex(), fmt!("%02x", i as uint));
}
}
#[test]
pub fn test_from_hex_all_bytes() {
for i in range(0, 256) {
assert_eq!(fmt!("%02x", i as uint).from_hex().unwrap(), ~[i as u8]);
assert_eq!(fmt!("%02X", i as uint).from_hex().unwrap(), ~[i as u8]);
}
}
#[bench]
pub fn bench_to_hex(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
do bh.iter {
s.as_bytes().to_hex();
}
bh.bytes = s.len() as u64;
}
#[bench]
pub fn bench_from_hex(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
let b = s.as_bytes().to_hex();
do bh.iter {
b.from_hex();
}
bh.bytes = b.len() as u64;
}
}
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*! Composable internal iterators
Internal iterators are functions implementing the protocol used by the `for` loop.
An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
tied to specific traits. For example:
~~~ {.rust}
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
~~~
An external iterator object implementing the interface in the `iterator` module can be used as an
internal iterator by calling the `advance` method. For example:
~~~ {.rust}
let xs = [0u, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let mut it = xs.iter().chain(ys.iter());
for &x: &uint in it {
println(x.to_str());
}
~~~
Internal iterators provide a subset of the functionality of an external iterator. It's not possible
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
much easier to implement.
*/
use std::vec;
use std::cmp::Ord;
use std::option::{Option, Some, None};
use std::num::{One, Zero};
use std::ops::{Add, Mul};
#[allow(missing_doc)]
pub trait FromIter<T> {
/// Build a container with elements from an internal iterator.
///
/// # Example:
///
/// ~~~ {.rust}
/// let xs = ~[1, 2, 3];
/// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
/// assert_eq!(xs, ys);
/// ~~~
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
}
/**
* Return true if `predicate` is true for any values yielded by an internal iterator.
*
* Example:
*
* ~~~ {.rust}
* let xs = ~[1u, 2, 3, 4, 5];
* assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
* assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
* ~~~
*/
#[inline]
pub fn any<T>(predicate: &fn(T) -> bool,
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
do iter |x| {
predicate(x)
}
}
/**
* Return true if `predicate` is true for all values yielded by an internal iterator.
*
* # Example:
*
* ~~~ {.rust}
* assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
* assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
* ~~~
*/
#[inline]
pub fn all<T>(predicate: &fn(T) -> bool,
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
// If we ever break, iter will return false, so this will only return true
// if predicate returns true for everything.
iter(|x| predicate(x))
}
/**
* Return the first element where `predicate` returns `true`. Return `None` if no element is found.
*
* # Example:
*
* ~~~ {.rust}
* let xs = ~[1u, 2, 3, 4, 5, 6];
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
* ~~~
*/
#[inline]
pub fn find<T>(predicate: &fn(&T) -> bool,
iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
let mut ret = None;
do iter |x| {
if predicate(&x) {
ret = Some(x);
false
} else { true }
};
ret
}
/**
* Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
*
* # Example:
*
* ~~~ {.rust}
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
* ~~~
*/
#[inline]
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
let mut result = None;
do iter |x| {
match result {
Some(ref mut y) => {
if x > *y {
*y = x;
}
}
None => result = Some(x)
}
true
};
result
}
/**
* Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
*
* # Example:
*
* ~~~ {.rust}
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5);
* ~~~
*/
#[inline]
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
let mut result = None;
do iter |x| {
match result {
Some(ref mut y) => {
if x < *y {
*y = x;
}
}
None => result = Some(x)
}
true
};
result
}
/**
* Reduce an iterator to an accumulated value.
*
* # Example:
*
* ~~~ {.rust}
* assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
* ~~~
*/
#[inline]
pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
let mut result = start;
do iter |x| {
f(&mut result, x);
true
};
result
}
/**
* Reduce an iterator to an accumulated value.
*
* `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
* forces the iterator to yield borrowed pointers.
*
* # Example:
*
* ~~~ {.rust}
* fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
* fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
* }
* ~~~
*/
#[inline]
pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
let mut result = start;
do iter |x| {
f(&mut result, x);
true
};
result
}
/**
* Return the sum of the items yielding by an iterator.
*
* # Example:
*
* ~~~ {.rust}
* let xs: ~[int] = ~[1, 2, 3, 4];
* assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
* ~~~
*/
#[inline]
pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
}
/**
* Return the product of the items yielded by an iterator.
*
* # Example:
*
* ~~~ {.rust}
* let xs: ~[int] = ~[1, 2, 3, 4];
* assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
* ~~~
*/
#[inline]
pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
}
impl<T> FromIter<T> for ~[T]{
#[inline]
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
let mut v = ~[];
do iter |x| { v.push(x); true };
v
}
}
#[cfg(test)]
mod tests {
use super::*;
use prelude::*;
use int;
use uint;
#[test]
fn test_from_iter() {
let xs = ~[1, 2, 3];
let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
assert_eq!(xs, ys);
}
#[test]
fn test_any() {
let xs = ~[1u, 2, 3, 4, 5];
assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
}
#[test]
fn test_all() {
assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
}
#[test]
fn test_find() {
let xs = ~[1u, 2, 3, 4, 5, 6];
assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
}
#[test]
fn test_max() {
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
}
#[test]
fn test_min() {
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5);
}
#[test]
fn test_fold() {
assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
}
#[test]
fn test_sum() {
let xs: ~[int] = ~[1, 2, 3, 4];
assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
}
#[test]
fn test_empty_sum() {
let xs: ~[int] = ~[];
assert_eq!(do sum |f| { xs.iter().advance(f) }, 0);
}
#[test]
fn test_product() {
let xs: ~[int] = ~[1, 2, 3, 4];
assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
}
#[test]
fn test_empty_product() {
let xs: ~[int] = ~[];
assert_eq!(do product |f| { xs.iter().advance(f) }, 1);
}
}
......@@ -696,7 +696,7 @@ fn test_from_iterator() {
let u: ~[int] = deq.iter().transform(|&x| x).collect();
assert_eq!(u, v);
let mut seq = iterator::Counter::new(0u, 2).take_(256);
let mut seq = iterator::count(0u, 2).take_(256);
let deq: RingBuf<uint> = seq.collect();
for (i, &x) in deq.iter().enumerate() {
assert_eq!(2*i, x);
......
......@@ -888,6 +888,11 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
let offset = get_param(decl, first_real_arg + 1);
Ret(bcx, GEP(bcx, ptr, [offset]));
}
"offset_inbounds" => {
let ptr = get_param(decl, first_real_arg);
let offset = get_param(decl, first_real_arg + 1);
Ret(bcx, InBoundsGEP(bcx, ptr, [offset]));
}
"memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
"memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
"memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
......
......@@ -148,7 +148,8 @@ fn store_type_uses(cx: Context, fn_id: def_id) -> @~[type_uses] {
"visit_tydesc" | "forget" | "frame_address" |
"morestack_addr" => 0,
"offset" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
"offset" | "offset_inbounds" |
"memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
"memset32" | "memset64" => use_repr,
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
......
......@@ -3481,6 +3481,20 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
mutbl: ast::m_imm
}))
}
"offset_inbounds" => {
(1,
~[
ty::mk_ptr(tcx, ty::mt {
ty: param(ccx, 0),
mutbl: ast::m_imm
}),
ty::mk_int()
],
ty::mk_ptr(tcx, ty::mt {
ty: param(ccx, 0),
mutbl: ast::m_imm
}))
}
"memcpy32" => {
(1,
~[
......
......@@ -637,7 +637,7 @@ fn should_request_new_writer_for_each_page() {
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
// We expect two pages to have been written
do 2.times {
for _ in range(0, 2u) {
po.recv();
}
}
......@@ -649,7 +649,7 @@ fn should_write_title_for_each_page() {
~"#[link(name = \"core\")]; mod a { }");
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
do 2.times {
for _ in range(0, 2u) {
let (page, markdown) = po.recv();
match page {
doc::CratePage(_) => {
......
......@@ -565,7 +565,10 @@ fn repl() -> Repl {
}
}
#[cfg(not(target_word_size = "32"))]
// FIXME: #7220 rusti on 32bit mac doesn't work.
// FIXME: #7641 rusti on 32bit linux cross compile doesn't work
// FIXME: #7115 re-enable once LLVM has been upgraded
#[cfg(thiswillneverbeacfgflag)]
fn run_program(prog: &str) {
let mut r = repl();
for cmd in prog.split_iter('\n') {
......@@ -574,9 +577,6 @@ fn run_program(prog: &str) {
"the command '%s' failed", cmd);
}
}
// FIXME: #7220 rusti on 32bit mac doesn't work
// FIXME: #7641 rusti on 32bit linux cross compile doesn't work
#[cfg(target_word_size = "32")]
fn run_program(_: &str) {}
#[test]
......@@ -594,12 +594,13 @@ fn regression_5784() {
run_program("let a = 3;");
}
#[test]
#[test] #[ignore]
fn new_tasks() {
// XXX: can't spawn new tasks because the JIT code is cleaned up
// after the main function is done.
run_program("
use std::task::try;
try( || println(\"Please don't segfault\") );
do try { println(\"Please?\"); }
spawn( || println(\"Please don't segfault\") );
do spawn { println(\"Please?\"); }
");
}
......
......@@ -58,3 +58,15 @@ fn gt(&self, other: & &'self T) -> bool {
*(*self) > *(*other)
}
}
#[cfg(not(test))]
impl<'self, T: TotalOrd> TotalOrd for &'self T {
#[inline]
fn cmp(&self, other: & &'self T) -> Ordering { (**self).cmp(*other) }
}
#[cfg(not(test))]
impl<'self, T: TotalEq> TotalEq for &'self T {
#[inline]
fn equals(&self, other: & &'self T) -> bool { (**self).equals(*other) }
}
......@@ -153,7 +153,6 @@ pub fn cmp2<A:TotalOrd,B:TotalOrd>(
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
lexical ordering on a type `(int, int)`.
*/
// used in deriving code in libsyntax
#[inline]
pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
match o1 {
......
......@@ -18,7 +18,7 @@
*/
use cmp;
use num::{Zero, One};
use num::{Zero, One, Saturating};
use option::{Option, Some, None};
use ops::{Add, Mul};
use cmp::Ord;
......@@ -313,7 +313,7 @@ fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
/// ~~~ {.rust}
/// let xs = [2u, 3];
/// let ys = [0u, 1, 0, 1, 2];
/// let mut it = xs.iter().flat_map_(|&x| Counter::new(0u, 1).take_(x));
/// let mut it = xs.iter().flat_map_(|&x| count(0u, 1).take_(x));
/// // Check that `it` has the same elements as `ys`
/// let mut i = 0;
/// for x: uint in it {
......@@ -351,7 +351,7 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
/// ~~~ {.rust}
/// use std::iterator::Counter;
///
/// for i in Counter::new(0, 10) {
/// for i in count(0, 10) {
/// printfln!("%d", i);
/// }
/// ~~~
......@@ -723,7 +723,7 @@ pub trait MultiplicativeIterator<A> {
/// use std::iterator::Counter;
///
/// fn factorial(n: uint) -> uint {
/// Counter::new(1u, 1).take_while(|&i| i <= n).product()
/// count(1u, 1).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
......@@ -790,7 +790,7 @@ pub trait ClonableIterator {
/// # Example
///
/// ~~~ {.rust}
/// let a = Counter::new(1,1).take_(1);
/// let a = count(1,1).take_(1);
/// let mut cy = a.cycle();
/// assert_eq!(cy.next(), Some(1));
/// assert_eq!(cy.next(), Some(1));
......@@ -884,15 +884,10 @@ fn size_hint(&self) -> (uint, Option<uint>) {
let (a_lower, a_upper) = self.a.size_hint();
let (b_lower, b_upper) = self.b.size_hint();
let lower = if uint::max_value - a_lower < b_lower {
uint::max_value
} else {
a_lower + b_lower
};
let lower = a_lower.saturating_add(b_lower);
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
(Some(x), Some(y)) => Some(x + y),
(Some(x), Some(y)) => Some(x.saturating_add(y)),
_ => None
};
......@@ -916,12 +911,7 @@ impl<A, T: RandomAccessIterator<A>, U: RandomAccessIterator<A>> RandomAccessIter
#[inline]
fn indexable(&self) -> uint {
let (a, b) = (self.a.indexable(), self.b.indexable());
let total = a + b;
if total < a || total < b {
uint::max_value
} else {
total
}
a.saturating_add(b)
}
#[inline]
......@@ -1273,11 +1263,10 @@ fn next(&mut self) -> Option<A> {
fn size_hint(&self) -> (uint, Option<uint>) {
let (lower, upper) = self.iter.size_hint();
let lower = if lower >= self.n { lower - self.n } else { 0 };
let lower = lower.saturating_sub(self.n);
let upper = match upper {
Some(x) if x >= self.n => Some(x - self.n),
Some(_) => Some(0),
Some(x) => Some(x.saturating_sub(self.n)),
None => None
};
......@@ -1288,12 +1277,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
#[inline]
fn indexable(&self) -> uint {
let N = self.iter.indexable();
if N < self.n {
0
} else {
N - self.n
}
self.iter.indexable().saturating_sub(self.n)
}
#[inline]
......@@ -1316,10 +1300,9 @@ pub struct Take<T> {
impl<A, T: Iterator<A>> Iterator<A> for Take<T> {
#[inline]
fn next(&mut self) -> Option<A> {
let next = self.iter.next();
if self.n != 0 {
self.n -= 1;
next
self.iter.next()
} else {
None
}
......@@ -1410,9 +1393,10 @@ fn next(&mut self) -> Option<B> {
fn size_hint(&self) -> (uint, Option<uint>) {
let (flo, fhi) = self.frontiter.map_default((0, Some(0)), |it| it.size_hint());
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (flo + blo, Some(a + b)),
_ => (flo + blo, None)
((0, Some(0)), Some(a), Some(b)) => (lo, Some(a.saturating_add(b))),
_ => (lo, None)
}
}
}
......@@ -1527,12 +1511,10 @@ pub struct Counter<A> {
step: A
}
impl<A> Counter<A> {
/// Creates a new counter with the specified start/step
#[inline]
pub fn new(start: A, step: A) -> Counter<A> {
Counter{state: start, step: step}
}
/// Creates a new counter with the specified start/step
#[inline]
pub fn count<A>(start: A, step: A) -> Counter<A> {
Counter{state: start, step: step}
}
/// A range of numbers from [0, N)
......@@ -1619,7 +1601,7 @@ mod tests {
#[test]
fn test_counter_from_iter() {
let mut it = Counter::new(0, 5).take_(10);
let mut it = count(0, 5).take_(10);
let xs: ~[int] = FromIterator::from_iterator(&mut it);
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
}
......@@ -1637,7 +1619,7 @@ fn test_iterator_chain() {
}
assert_eq!(i, expected.len());
let ys = Counter::new(30u, 10).take_(4);
let ys = count(30u, 10).take_(4);
let mut it = xs.iter().transform(|&x| x).chain_(ys);
let mut i = 0;
for x in it {
......@@ -1649,7 +1631,7 @@ fn test_iterator_chain() {
#[test]
fn test_filter_map() {
let mut it = Counter::new(0u, 1u).take_(10)
let mut it = count(0u, 1u).take_(10)
.filter_map(|x| if x.is_even() { Some(x*x) } else { None });
assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
}
......@@ -1738,7 +1720,7 @@ fn add(old: &mut int, new: &uint) -> Option<float> {
fn test_iterator_flat_map() {
let xs = [0u, 3, 6];
let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
let mut it = xs.iter().flat_map_(|&x| Counter::new(x, 1).take_(3));
let mut it = xs.iter().flat_map_(|&x| count(x, 1).take_(3));
let mut i = 0;
for x in it {
assert_eq!(x, ys[i]);
......@@ -1785,13 +1767,13 @@ fn count(st: &mut uint) -> Option<uint> {
#[test]
fn test_cycle() {
let cycle_len = 3;
let it = Counter::new(0u, 1).take_(cycle_len).cycle();
let it = count(0u, 1).take_(cycle_len).cycle();
assert_eq!(it.size_hint(), (uint::max_value, None));
for (i, x) in it.take_(100).enumerate() {
assert_eq!(i % cycle_len, x);
}
let mut it = Counter::new(0u, 1).take_(0).cycle();
let mut it = count(0u, 1).take_(0).cycle();
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
......@@ -1853,7 +1835,7 @@ fn test_iterator_min() {
#[test]
fn test_iterator_size_hint() {
let c = Counter::new(0, 1);
let c = count(0, 1);
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let v2 = &[10, 11, 12];
let vi = v.iter();
......
......@@ -12,7 +12,7 @@
use ptr::to_unsafe_ptr;
#[cfg(not(test))] use cmp::{Eq, Ord};
#[cfg(not(test))] use cmp::*;
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
pub static RC_IMMORTAL : uint = 0x77777777;
......@@ -71,6 +71,29 @@ fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) }
fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
}
#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for @T {
#[inline]
fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
}
#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for @mut T {
#[inline]
fn cmp(&self, other: &@mut T) -> Ordering { (**self).cmp(*other) }
}
#[cfg(not(test))]
impl<T: TotalEq> TotalEq for @T {
#[inline]
fn equals(&self, other: &@T) -> bool { (**self).equals(*other) }
}
#[cfg(not(test))]
impl<T: TotalEq> TotalEq for @mut T {
#[inline]
fn equals(&self, other: &@mut T) -> bool { (**self).equals(*other) }
}
#[test]
fn test() {
let x = @3;
......
......@@ -466,6 +466,56 @@ fn zero() -> ~T { ~Zero::zero() }
fn is_zero(&self) -> bool { (**self).is_zero() }
}
/// Saturating math operations
pub trait Saturating: Int {
/// Saturating addition operator.
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
#[inline]
fn saturating_add(self, v: Self) -> Self {
let x = self + v;
if v >= Zero::zero() {
if x < self {
// overflow
Bounded::max_value::<Self>()
} else { x }
} else {
if x > self {
// underflow
Bounded::min_value::<Self>()
} else { x }
}
}
/// Saturating subtraction operator.
/// Returns a-b, saturating at the numeric bounds instead of overflowing.
#[inline]
fn saturating_sub(self, v: Self) -> Self {
let x = self - v;
if v >= Zero::zero() {
if x > self {
// underflow
Bounded::min_value::<Self>()
} else { x }
} else {
if x < self {
// overflow
Bounded::max_value::<Self>()
} else { x }
}
}
}
impl Saturating for int {}
impl Saturating for i8 {}
impl Saturating for i16 {}
impl Saturating for i32 {}
impl Saturating for i64 {}
impl Saturating for uint {}
impl Saturating for u8 {}
impl Saturating for u16 {}
impl Saturating for u32 {}
impl Saturating for u64 {}
/// Helper function for testing numeric operations
#[cfg(test)]
pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
......@@ -482,64 +532,111 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
assert_eq!(ten.rem(&two), ten % two);
}
macro_rules! test_cast_20(
($_20:expr) => ({
let _20 = $_20;
assert_eq!(20u, _20.to_uint());
assert_eq!(20u8, _20.to_u8());
assert_eq!(20u16, _20.to_u16());
assert_eq!(20u32, _20.to_u32());
assert_eq!(20u64, _20.to_u64());
assert_eq!(20i, _20.to_int());
assert_eq!(20i8, _20.to_i8());
assert_eq!(20i16, _20.to_i16());
assert_eq!(20i32, _20.to_i32());
assert_eq!(20i64, _20.to_i64());
assert_eq!(20f, _20.to_float());
assert_eq!(20f32, _20.to_f32());
assert_eq!(20f64, _20.to_f64());
assert_eq!(_20, NumCast::from(20u));
assert_eq!(_20, NumCast::from(20u8));
assert_eq!(_20, NumCast::from(20u16));
assert_eq!(_20, NumCast::from(20u32));
assert_eq!(_20, NumCast::from(20u64));
assert_eq!(_20, NumCast::from(20i));
assert_eq!(_20, NumCast::from(20i8));
assert_eq!(_20, NumCast::from(20i16));
assert_eq!(_20, NumCast::from(20i32));
assert_eq!(_20, NumCast::from(20i64));
assert_eq!(_20, NumCast::from(20f));
assert_eq!(_20, NumCast::from(20f32));
assert_eq!(_20, NumCast::from(20f64));
assert_eq!(_20, cast(20u));
assert_eq!(_20, cast(20u8));
assert_eq!(_20, cast(20u16));
assert_eq!(_20, cast(20u32));
assert_eq!(_20, cast(20u64));
assert_eq!(_20, cast(20i));
assert_eq!(_20, cast(20i8));
assert_eq!(_20, cast(20i16));
assert_eq!(_20, cast(20i32));
assert_eq!(_20, cast(20i64));
assert_eq!(_20, cast(20f));
assert_eq!(_20, cast(20f32));
assert_eq!(_20, cast(20f64));
})
)
#[cfg(test)]
mod tests {
use super::*;
macro_rules! test_cast_20(
($_20:expr) => ({
let _20 = $_20;
assert_eq!(20u, _20.to_uint());
assert_eq!(20u8, _20.to_u8());
assert_eq!(20u16, _20.to_u16());
assert_eq!(20u32, _20.to_u32());
assert_eq!(20u64, _20.to_u64());
assert_eq!(20i, _20.to_int());
assert_eq!(20i8, _20.to_i8());
assert_eq!(20i16, _20.to_i16());
assert_eq!(20i32, _20.to_i32());
assert_eq!(20i64, _20.to_i64());
assert_eq!(20f, _20.to_float());
assert_eq!(20f32, _20.to_f32());
assert_eq!(20f64, _20.to_f64());
assert_eq!(_20, NumCast::from(20u));
assert_eq!(_20, NumCast::from(20u8));
assert_eq!(_20, NumCast::from(20u16));
assert_eq!(_20, NumCast::from(20u32));
assert_eq!(_20, NumCast::from(20u64));
assert_eq!(_20, NumCast::from(20i));
assert_eq!(_20, NumCast::from(20i8));
assert_eq!(_20, NumCast::from(20i16));
assert_eq!(_20, NumCast::from(20i32));
assert_eq!(_20, NumCast::from(20i64));
assert_eq!(_20, NumCast::from(20f));
assert_eq!(_20, NumCast::from(20f32));
assert_eq!(_20, NumCast::from(20f64));
assert_eq!(_20, cast(20u));
assert_eq!(_20, cast(20u8));
assert_eq!(_20, cast(20u16));
assert_eq!(_20, cast(20u32));
assert_eq!(_20, cast(20u64));
assert_eq!(_20, cast(20i));
assert_eq!(_20, cast(20i8));
assert_eq!(_20, cast(20i16));
assert_eq!(_20, cast(20i32));
assert_eq!(_20, cast(20i64));
assert_eq!(_20, cast(20f));
assert_eq!(_20, cast(20f32));
assert_eq!(_20, cast(20f64));
})
)
#[test] fn test_u8_cast() { test_cast_20!(20u8) }
#[test] fn test_u16_cast() { test_cast_20!(20u16) }
#[test] fn test_u32_cast() { test_cast_20!(20u32) }
#[test] fn test_u64_cast() { test_cast_20!(20u64) }
#[test] fn test_uint_cast() { test_cast_20!(20u) }
#[test] fn test_i8_cast() { test_cast_20!(20i8) }
#[test] fn test_i16_cast() { test_cast_20!(20i16) }
#[test] fn test_i32_cast() { test_cast_20!(20i32) }
#[test] fn test_i64_cast() { test_cast_20!(20i64) }
#[test] fn test_int_cast() { test_cast_20!(20i) }
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
#[test] fn test_float_cast() { test_cast_20!(20f) }
#[test]
fn test_saturating_add_uint() {
use uint::max_value;
assert_eq!(3u.saturating_add(5u), 8u);
assert_eq!(3u.saturating_add(max_value-1), max_value);
assert_eq!(max_value.saturating_add(max_value), max_value);
assert_eq!((max_value-2).saturating_add(1), max_value-1);
}
#[test]
fn test_saturating_sub_uint() {
use uint::max_value;
assert_eq!(5u.saturating_sub(3u), 2u);
assert_eq!(3u.saturating_sub(5u), 0u);
assert_eq!(0u.saturating_sub(1u), 0u);
assert_eq!((max_value-1).saturating_sub(max_value), 0);
}
#[test] fn test_u8_cast() { test_cast_20!(20u8) }
#[test] fn test_u16_cast() { test_cast_20!(20u16) }
#[test] fn test_u32_cast() { test_cast_20!(20u32) }
#[test] fn test_u64_cast() { test_cast_20!(20u64) }
#[test] fn test_uint_cast() { test_cast_20!(20u) }
#[test] fn test_i8_cast() { test_cast_20!(20i8) }
#[test] fn test_i16_cast() { test_cast_20!(20i16) }
#[test] fn test_i32_cast() { test_cast_20!(20i32) }
#[test] fn test_i64_cast() { test_cast_20!(20i64) }
#[test] fn test_int_cast() { test_cast_20!(20i) }
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
#[test] fn test_float_cast() { test_cast_20!(20f) }
#[test]
fn test_saturating_add_int() {
use int::{min_value,max_value};
assert_eq!(3i.saturating_add(5i), 8i);
assert_eq!(3i.saturating_add(max_value-1), max_value);
assert_eq!(max_value.saturating_add(max_value), max_value);
assert_eq!((max_value-2).saturating_add(1), max_value-1);
assert_eq!(3i.saturating_add(-5i), -2i);
assert_eq!(min_value.saturating_add(-1i), min_value);
assert_eq!((-2i).saturating_add(-max_value), min_value);
}
#[test]
fn test_saturating_sub_int() {
use int::{min_value,max_value};
assert_eq!(3i.saturating_sub(5i), -2i);
assert_eq!(min_value.saturating_sub(1i), min_value);
assert_eq!((-2i).saturating_sub(max_value), min_value);
assert_eq!(3i.saturating_sub(-5i), 8i);
assert_eq!(3i.saturating_sub(-(max_value-1)), max_value);
assert_eq!(max_value.saturating_sub(-max_value), max_value);
assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
}
}
......@@ -10,7 +10,7 @@
//! Operations on unique pointer types
#[cfg(not(test))] use cmp::{Eq, Ord};
#[cfg(not(test))] use cmp::*;
#[cfg(not(test))]
impl<T:Eq> Eq for ~T {
......@@ -31,3 +31,15 @@ fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) }
#[inline]
fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
}
#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for ~T {
#[inline]
fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) }
}
#[cfg(not(test))]
impl<T: TotalEq> TotalEq for ~T {
#[inline]
fn equals(&self, other: &~T) -> bool { (**self).equals(*other) }
}
......@@ -50,6 +50,7 @@
pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
pub use hash::Hash;
pub use iter::Times;
pub use iterator::Extendable;
pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
pub use iterator::{ClonableIterator, OrdIterator};
pub use num::{Num, NumCast};
......@@ -65,7 +66,7 @@
pub use ptr::RawPtr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
pub use str::{Str, StrVector, StrSlice, OwnedStr};
pub use from_str::{FromStr};
pub use from_str::FromStr;
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume};
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
......
......@@ -272,6 +272,7 @@ pub trait RawPtr<T> {
fn is_not_null(&self) -> bool;
unsafe fn to_option(&self) -> Option<&T>;
fn offset(&self, count: int) -> Self;
unsafe fn offset_inbounds(self, count: int) -> Self;
}
/// Extension methods for immutable pointers
......@@ -304,6 +305,22 @@ unsafe fn to_option(&self) -> Option<&T> {
/// Calculates the offset from a pointer.
#[inline]
fn offset(&self, count: int) -> *T { offset(*self, count) }
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end.
#[inline]
#[cfg(stage0)]
unsafe fn offset_inbounds(self, count: int) -> *T {
intrinsics::offset(self, count)
}
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end.
#[inline]
#[cfg(not(stage0))]
unsafe fn offset_inbounds(self, count: int) -> *T {
intrinsics::offset_inbounds(self, count)
}
}
/// Extension methods for mutable pointers
......@@ -336,6 +353,30 @@ unsafe fn to_option(&self) -> Option<&T> {
/// Calculates the offset from a mutable pointer.
#[inline]
fn offset(&self, count: int) -> *mut T { mut_offset(*self, count) }
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
/// undefined behaviour.
///
/// This method should be preferred over `offset` when the guarantee can be
/// satisfied, to enable better optimization.
#[inline]
#[cfg(stage0)]
unsafe fn offset_inbounds(self, count: int) -> *mut T {
intrinsics::offset(self as *T, count) as *mut T
}
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
/// undefined behaviour.
///
/// This method should be preferred over `offset` when the guarantee can be
/// satisfied, to enable better optimization.
#[inline]
#[cfg(not(stage0))]
unsafe fn offset_inbounds(self, count: int) -> *mut T {
intrinsics::offset_inbounds(self as *T, count) as *mut T
}
}
// Equality for pointers
......
......@@ -3483,19 +3483,22 @@ fn test_char_range_at_reverse_underflow() {
fn test_add() {
#[allow(unnecessary_allocation)];
macro_rules! t (
($s1:expr, $s2:expr, $e:expr) => {
assert_eq!($s1 + $s2, $e);
assert_eq!($s1.to_owned() + $s2, $e);
assert_eq!($s1.to_managed() + $s2, $e);
}
($s1:expr, $s2:expr, $e:expr) => { {
let s1 = $s1;
let s2 = $s2;
let e = $e;
assert_eq!(s1 + s2, e.to_owned());
assert_eq!(s1.to_owned() + s2, e.to_owned());
assert_eq!(s1.to_managed() + s2, e.to_owned());
} }
);
t!("foo", "bar", ~"foobar");
t!("foo", @"bar", ~"foobar");
t!("foo", ~"bar", ~"foobar");
t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam");
t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam");
t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam");
t!("foo", "bar", "foobar");
t!("foo", @"bar", "foobar");
t!("foo", ~"bar", "foobar");
t!("ศไทย中", "华Việt Nam", "ศไทย中华Việt Nam");
t!("ศไทย中", @"华Việt Nam", "ศไทย中华Việt Nam");
t!("ศไทย中", ~"华Việt Nam", "ศไทย中华Việt Nam");
}
#[test]
......
......@@ -13,7 +13,10 @@
use to_str::{ToStr,ToStrConsume};
use str;
use str::StrSlice;
use str::OwnedStr;
use container::Container;
use cast;
use ptr;
use iterator::{Iterator, IteratorUtil};
use vec::{CopyableVector, ImmutableVector};
#[cfg(stage0)]
......@@ -41,27 +44,19 @@ pub fn to_char(self) -> char {
/// Convert to lowercase.
#[inline]
pub fn to_lower(self) -> Ascii {
if self.chr >= 65 && self.chr <= 90 {
Ascii{chr: self.chr | 0x20 }
} else {
self
}
Ascii{chr: ASCII_LOWER_MAP[self.chr]}
}
/// Convert to uppercase.
#[inline]
pub fn to_upper(self) -> Ascii {
if self.chr >= 97 && self.chr <= 122 {
Ascii{chr: self.chr & !0x20 }
} else {
self
}
Ascii{chr: ASCII_UPPER_MAP[self.chr]}
}
/// Compares two ascii characters of equality, ignoring case.
#[inline]
pub fn eq_ignore_case(self, other: Ascii) -> bool {
self.to_lower().chr == other.to_lower().chr
ASCII_LOWER_MAP[self.chr] == ASCII_LOWER_MAP[other.chr]
}
}
......@@ -292,10 +287,124 @@ fn into_bytes(self) -> ~[u8] {
}
}
/// Convert the string to ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
#[inline]
pub fn to_ascii_upper(string: &str) -> ~str {
map_bytes(string, ASCII_UPPER_MAP)
}
/// Convert the string to ASCII lower case:
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
#[inline]
pub fn to_ascii_lower(string: &str) -> ~str {
map_bytes(string, ASCII_LOWER_MAP)
}
#[inline]
priv fn map_bytes(string: &str, map: &'static [u8]) -> ~str {
let len = string.len();
let mut result = str::with_capacity(len);
unsafe {
do result.as_mut_buf |mut buf, _| {
for c in string.as_bytes().iter() {
*buf = map[*c];
buf = ptr::mut_offset(buf, 1)
}
}
str::raw::set_len(&mut result, len);
}
result
}
/// Check that two strings are an ASCII case-insensitive match.
/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
/// but without allocating and copying temporary strings.
#[inline]
pub fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
a.len() == b.len() && a.as_bytes().iter().zip(b.as_bytes().iter()).all(
|(byte_a, byte_b)| ASCII_LOWER_MAP[*byte_a] == ASCII_LOWER_MAP[*byte_b])
}
priv static ASCII_LOWER_MAP: &'static [u8] = &[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
priv static ASCII_UPPER_MAP: &'static [u8] = &[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
#[cfg(test)]
mod tests {
use super::*;
use to_bytes::ToBytes;
use str::from_char;
macro_rules! v2ascii (
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
......@@ -378,4 +487,53 @@ fn test_ascii_to_bytes() {
#[test] #[should_fail]
fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
#[test]
fn test_to_ascii_upper() {
assert_eq!(to_ascii_upper("url()URL()uRl()ürl"), ~"URL()URL()URL()üRL");
assert_eq!(to_ascii_upper("hıKß"), ~"HıKß");
let mut i = 0;
while i <= 500 {
let c = i as char;
let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c };
assert_eq!(to_ascii_upper(from_char(i as char)), from_char(upper))
i += 1;
}
}
#[test]
fn test_to_ascii_lower() {
assert_eq!(to_ascii_lower("url()URL()uRl()Ürl"), ~"url()url()url()Ürl");
// Dotted capital I, Kelvin sign, Sharp S.
assert_eq!(to_ascii_lower("HİKß"), ~"hİKß");
let mut i = 0;
while i <= 500 {
let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
assert_eq!(to_ascii_lower(from_char(i as char)), from_char(lower))
i += 1;
}
}
#[test]
fn test_eq_ignore_ascii_case() {
assert!(eq_ignore_ascii_case("url()URL()uRl()Ürl", "url()url()url()Ürl"));
assert!(!eq_ignore_ascii_case("Ürl", "ürl"));
// Dotted capital I, Kelvin sign, Sharp S.
assert!(eq_ignore_ascii_case("HİKß", "hİKß"));
assert!(!eq_ignore_ascii_case("İ", "i"));
assert!(!eq_ignore_ascii_case("K", "k"));
assert!(!eq_ignore_ascii_case("ß", "s"));
let mut i = 0;
while i <= 500 {
let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
assert!(eq_ignore_ascii_case(from_char(i as char), from_char(lower)));
i += 1;
}
}
}
......@@ -317,12 +317,21 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
/// Get the address of the `__morestack` stack growth function.
pub fn morestack_addr() -> *();
/// Adjust a pointer by an offset.
/// Calculates the offset from a pointer.
///
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
pub fn offset<T>(dst: *T, offset: int) -> *T;
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
/// undefined behaviour.
///
/// This intrinsic should be preferred over `offset` when the guarantee can
/// be satisfied, to enable better optimization.
#[cfg(not(stage0))]
pub fn offset_inbounds<T>(dst: *T, offset: int) -> *T;
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);
......
......@@ -849,10 +849,15 @@ fn slice_to(&self, end: uint) -> &'self [T] {
fn iter(self) -> VecIterator<'self, T> {
unsafe {
let p = vec::raw::to_ptr(self);
VecIterator{ptr: p,
end: (p as uint + self.len() *
sys::nonzero_size_of::<T>()) as *T,
lifetime: cast::transmute(p)}
if sys::size_of::<T>() == 0 {
VecIterator{ptr: p,
end: (p as uint + self.len()) as *T,
lifetime: cast::transmute(p)}
} else {
VecIterator{ptr: p,
end: p.offset_inbounds(self.len() as int),
lifetime: cast::transmute(p)}
}
}
}
......@@ -1826,10 +1831,15 @@ fn mut_split(self, mid: uint) -> (&'self mut [T], &'self mut [T]) {
fn mut_iter(self) -> VecMutIterator<'self, T> {
unsafe {
let p = vec::raw::to_mut_ptr(self);
VecMutIterator{ptr: p,
end: (p as uint + self.len() *
sys::nonzero_size_of::<T>()) as *mut T,
lifetime: cast::transmute(p)}
if sys::size_of::<T>() == 0 {
VecMutIterator{ptr: p,
end: (p as uint + self.len()) as *mut T,
lifetime: cast::transmute(p)}
} else {
VecMutIterator{ptr: p,
end: p.offset_inbounds(self.len() as int),
lifetime: cast::transmute(p)}
}
}
}
......@@ -2183,7 +2193,7 @@ fn next(&mut self) -> Option<$elem> {
// same pointer.
cast::transmute(self.ptr as uint + 1)
} else {
self.ptr.offset(1)
self.ptr.offset_inbounds(1)
};
Some(cast::transmute(old))
......@@ -2215,7 +2225,7 @@ fn next_back(&mut self) -> Option<$elem> {
// See above for why 'ptr.offset' isn't used
cast::transmute(self.end as uint - 1)
} else {
self.end.offset(-1)
self.end.offset_inbounds(-1)
};
Some(cast::transmute(self.end))
}
......
......@@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast;
use ast::{MetaItem, item, expr};
use codemap::span;
use ext::base::ExtCtxt;
......@@ -40,40 +41,70 @@ pub fn expand_deriving_totalord(cx: @ExtCtxt,
}
pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> @expr {
pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> ast::Path {
let cnst = match cnst {
Less => "Less",
Equal => "Equal",
Greater => "Greater"
};
cx.expr_path(
cx.path_global(span,
~[cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of(cnst)]))
cx.path_global(span,
~[cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of(cnst)])
}
pub fn cs_cmp(cx: @ExtCtxt, span: span,
substr: &Substructure) -> @expr {
let test_id = cx.ident_of("__test");
let equals_path = ordering_const(cx, span, Equal);
/*
Builds:
let __test = self_field1.cmp(&other_field2);
if other == ::std::cmp::Equal {
let __test = self_field2.cmp(&other_field2);
if __test == ::std::cmp::Equal {
...
} else {
__test
}
} else {
__test
}
FIXME #6449: These `if`s could/should be `match`es.
*/
cs_same_method_fold(
// foldr (possibly) nests the matches in lexical_ordering better
// foldr nests the if-elses correctly, leaving the first field
// as the outermost one, and the last as the innermost.
false,
|cx, span, old, new| {
cx.expr_call_global(span,
~[cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of("lexical_ordering")],
~[old, new])
// let __test = new;
// if __test == ::std::cmp::Equal {
// old
// } else {
// __test
// }
let assign = cx.stmt_let(span, false, test_id, new);
let cond = cx.expr_binary(span, ast::eq,
cx.expr_ident(span, test_id),
cx.expr_path(equals_path.clone()));
let if_ = cx.expr_if(span,
cond,
old, Some(cx.expr_ident(span, test_id)));
cx.expr_block(cx.block(span, ~[assign], Some(if_)))
},
ordering_const(cx, span, Equal),
cx.expr_path(equals_path.clone()),
|cx, span, list, _| {
match list {
// an earlier nonmatching variant is Less than a
// later one
// later one.
[(self_var, _, _),
(other_var, _, _)] => ordering_const(cx, span,
self_var.cmp(&other_var)),
(other_var, _, _)] => cx.expr_path(ordering_const(cx, span,
self_var.cmp(&other_var))),
_ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`")
}
},
......
......@@ -59,7 +59,7 @@ pub fn bench_int<T:MutableSet<uint>,
{
let mut set = f();
do timed(&mut self.random_ints) {
do num_keys.times {
for _ in range(0, num_keys) {
set.insert((rng.next() as uint) % rand_cap);
}
}
......@@ -103,7 +103,7 @@ pub fn bench_str<T:MutableSet<~str>,
{
let mut set = f();
do timed(&mut self.random_strings) {
do num_keys.times {
for _ in range(0, num_keys) {
let s = uint::to_str(rng.next() as uint);
set.insert(s);
}
......
......@@ -105,7 +105,7 @@ fn main() {
let symbols = [" ", "░", "▒", "▓", "█", "█"];
let mut pixels = [0f32, ..256*256];
let n2d = ~Noise2DContext::new();
do 100.times {
for _ in range(0, 100u) {
for y in range(0, 256) {
for x in range(0, 256) {
let v = n2d.get(
......
......@@ -169,7 +169,7 @@ fn rendezvous(nn: uint, set: ~[color]) {
let mut creatures_met = 0;
// set up meetings...
do nn.times {
for _ in range(0, nn) {
let fst_creature: CreatureInfo = from_creatures.recv();
let snd_creature: CreatureInfo = from_creatures.recv();
......
......@@ -164,7 +164,7 @@ fn make(&mut self, n: uint) {
let chars_left = n % LINE_LEN;
let mut buf = [0, ..LINE_LEN + 1];
do lines.times {
for _ in range(0, lines) {
for i in range(0u, LINE_LEN) {
buf[i] = self.nextc();
}
......
......@@ -54,7 +54,7 @@ fn pack(string: &str) -> Code {
fn unpack(&self, frame: i32) -> ~str {
let mut key = **self;
let mut result = ~[];
do (frame as uint).times {
for _ in range(0, frame) {
result.push(unpack_symbol((key as u8) & 3));
key >>= 2;
}
......@@ -251,7 +251,7 @@ fn generate_frequencies(frequencies: &mut Table,
let mut code = Code(0);
// Pull first frame.
do (frame as uint).times {
for _ in range(0, frame) {
code = code.push_char(input[0]);
input = next_char(input);
}
......
......@@ -79,7 +79,7 @@ struct Planet {
fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) {
let mut d = [ 0.0, ..3 ];
do (steps as uint).times {
for _ in range(0, steps) {
for i in range(0u, N_BODIES) {
for j in range(i + 1, N_BODIES) {
d[0] = bodies[i].x[0] - bodies[j].x[0];
......
......@@ -56,7 +56,7 @@ fn main() {
let mut u = vec::from_elem(n, 1f64);
let mut v = u.clone();
let mut tmp = u.clone();
do 8.times {
for _ in range(0, 8u) {
mult_AtAv(u, v, tmp);
mult_AtAv(v, u, tmp);
}
......
......@@ -32,7 +32,7 @@ fn main() {
}
fn run(repeat: int, depth: int) {
do (repeat as uint).times {
for _ in range(0, repeat) {
info!("starting %.4f", precise_time_s());
do task::try {
recurse_or_fail(depth, None)
......
......@@ -32,7 +32,7 @@ fn grandchild_group(num_tasks: uint) {
let (po, ch) = stream();
let ch = SharedChan::new(ch);
do num_tasks.times {
for _ in range(0, num_tasks) {
let ch = ch.clone();
do task::spawn { // linked
ch.send(());
......@@ -41,7 +41,7 @@ fn grandchild_group(num_tasks: uint) {
}
}
error!("Grandchild group getting started");
do num_tasks.times {
for _ in range(0, num_tasks) {
// Make sure all above children are fully spawned; i.e., enlisted in
// their ancestor groups.
po.recv();
......
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test FIXME #7307
// xfail-fast
extern mod extra;
use extra::oldmap::*;
class cat : map<int, bool> {
priv {
// Yes, you can have negative meows
let mut meows : int;
fn meow() {
self.meows += 1;
error!("Meow %d", self.meows);
if self.meows % 5 == 0 {
self.how_hungry += 1;
}
}
}
let mut how_hungry : int;
let name : str;
new(in_x : int, in_y : int, in_name: str)
{ self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }
fn speak() { self.meow(); }
fn eat() -> bool {
if self.how_hungry > 0 {
error!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
error!("Not hungry!");
return false;
}
}
fn size() -> uint { self.meows as uint }
fn insert(+k: int, +v: bool) -> bool {
if v { self.meows += k; } else { self.meows -= k; };
true
}
fn contains_key(&&k: int) -> bool { k <= self.meows }
fn get(&&k:int) -> bool { k <= self.meows }
fn [](&&k:int) -> bool { k <= self.meows }
fn find(&&k:int) -> Option<bool> { Some(self.get(k)) }
fn remove(&&k:int) -> Option<bool> { self.meows -= k; Some(true) }
fn each(f: &fn(&&int, &&bool) -> bool) {
let mut n = num::abs(self.meows);
while n > 0 {
if !f(n, true) { break; }
n -= 1;
}
}
fn each_key(&&f: &fn(&&int) -> bool) {
for self.each |k, _v| { if !f(k) { break; } again;};
}
fn each_value(&&f: &fn(&&bool) -> bool) {
for self.each |_k, v| { if !f(v) { break; } again;};
}
fn clear() { }
}
pub fn main() {
let nyan : cat = cat(0, 2, "nyan");
for _ in range(1u, 5u) { nyan.speak(); }
// cat returns true if uint input is greater than
// the number of meows so far
assert!((nyan.get(1)));
assert!((!nyan.get(10)));
}
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test FIXME #7305
extern mod extra;
use extra::oldmap::*;
use vec::*;
use dvec::{dvec, extensions};
enum furniture { chair, couch, bed }
enum body_part { finger, toe, nose, ear }
trait noisy {
fn speak() -> int;
}
trait scratchy {
fn scratch() -> Option<furniture>;
}
trait bitey {
fn bite() -> body_part;
}
fn vec_includes<T>(xs: ~[T], x: T) -> bool {
for each(xs) |y| { if y == x { return true; }}
return false;
}
// vtables other than the 1st one don't seem to work
class cat : noisy, scratchy, bitey {
priv {
let meows : @mut uint;
let scratched : dvec<furniture>;
let bite_counts : hashmap<body_part, uint>;
fn meow() -> uint {
info!("Meow: %u", *self.meows);
*self.meows += 1u;
if *self.meows % 5u == 0u {
*self.how_hungry += 1;
}
*self.meows
}
}
let how_hungry : @mut int;
let name : str;
new(in_x : uint, in_y : int, in_name: str)
{ self.meows = @mut in_x; self.how_hungry = @mut in_y;
self.name = in_name; self.scratched = dvec();
let hsher: hashfn<body_part> = |p| int::hash(p as int);
let eqer : eqfn<body_part> = |p, q| p == q;
let t : hashmap<body_part, uint> =
hashmap::<body_part, uint>(hsher, eqer);
self.bite_counts = t;
do iter(~[finger, toe, nose, ear]) |p| {
self.bite_counts.insert(p, 0u);
};
}
fn speak() -> int { self.meow() as int }
fn meow_count() -> uint { *self.meows }
fn scratch() -> Option<furniture> {
let all = ~[chair, couch, bed];
log(error, self.scratched);
let mut rslt = None;
for each(all) |thing| { if !self.scratched.contains(thing) {
self.scratched.push(thing);
return Some(thing); }}
rslt
}
fn bite() -> body_part {
error!("In bite()");
let all = ~[toe, nose, ear];
let mut min = finger;
do iter(all) |next| {
info!("min = %?", min);
if self.bite_counts.get(next) < self.bite_counts.get(min) {
min = next;
}};
self.bite_counts.insert(min, self.bite_counts.get(min) + 1u);
info!("Bit %?", min);
min
}
}
fn annoy_neighbors<T:noisy>(critter: T) {
for i in range(0u, 10u) {
let what = critter.speak();
info!("%u %d", i, what);
}
}
fn bite_everything<T:bitey>(critter: T) -> bool {
let mut left : ~[body_part] = ~[finger, toe, nose, ear];
while left.len() > 0u {
let part = critter.bite();
info!("%? %?", left, part);
if vec_includes(left, part) {
left = vec::filter(left, |p| p != part );
}
else {
return false;
}
}
true
}
fn scratched_something<T:scratchy>(critter: T) -> bool {
option::is_some(critter.scratch())
}
pub fn main() {
let nyan : cat = cat(0u, 2, "nyan");
annoy_neighbors(nyan as noisy);
assert_eq!(nyan.meow_count(), 10u);
assert!((bite_everything(nyan as bitey)));
assert!((scratched_something(nyan as scratchy)));
}
......@@ -12,10 +12,4 @@ fn sum_imm(y: &[int]) -> int {
sum(y)
}
/* FIXME #7304
fn sum_const(y: &const [int]) -> int {
sum(y)
}
*/
pub fn main() {}
/* FIXME #7302
fn foo(v: &const [uint]) -> ~[uint] {
v.to_owned()
}
*/
fn bar(v: &mut [uint]) -> ~[uint] {
v.to_owned()
}
......@@ -14,7 +8,6 @@ fn bip(v: &[uint]) -> ~[uint] {
pub fn main() {
let mut the_vec = ~[1u, 2, 3, 100];
// assert_eq!(the_vec.clone(), foo(the_vec));
assert_eq!(the_vec.clone(), bar(the_vec));
assert_eq!(the_vec.clone(), bip(the_vec));
}
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// check that the derived impls for the comparison traits shortcircuit
// where possible, by having a type that fails when compared as the
// second element, so this passes iff the instances shortcircuit.
pub struct FailCmp;
impl Eq for FailCmp {
fn eq(&self, _: &FailCmp) -> bool { fail!("eq") }
}
impl Ord for FailCmp {
fn lt(&self, _: &FailCmp) -> bool { fail!("lt") }
}
impl TotalEq for FailCmp {
fn equals(&self, _: &FailCmp) -> bool { fail!("equals") }
}
impl TotalOrd for FailCmp {
fn cmp(&self, _: &FailCmp) -> Ordering { fail!("cmp") }
}
#[deriving(Eq,Ord,TotalEq,TotalOrd)]
struct ShortCircuit {
x: int,
y: FailCmp
}
fn main() {
let a = ShortCircuit { x: 1, y: FailCmp };
let b = ShortCircuit { x: 2, y: FailCmp };
assert!(a != b);
assert!(a < b);
assert!(!a.equals(&b));
assert_eq!(a.cmp(&b), ::std::cmp::Less);
}
......@@ -12,7 +12,9 @@ trait get {
fn get(self) -> int;
}
// FIXME #7302: Note: impl on a slice
// Note: impl on a slice; we're checking that the pointers below
// correctly get borrowed to `&`. (similar to impling for `int`, with
// `&self` instead of `self`.)
impl<'self> get for &'self int {
fn get(self) -> int {
return *self;
......@@ -34,11 +36,6 @@ pub fn main() {
info!("y=%d", y);
assert_eq!(y, 6);
let x = ~6;
let y = x.get();
info!("y=%d", y);
assert_eq!(y, 6);
let x = &6;
let y = x.get();
info!("y=%d", y);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册