Merge remote-tracking branch 'mozilla/master'

Conflicts:
	src/libextra/test.rs
	src/libstd/at_vec.rs
	src/libstd/cleanup.rs
	src/libstd/rt/comm.rs
	src/libstd/rt/global_heap.rs
	src/libstd/task/spawn.rs
	src/libstd/unstable/lang.rs
	src/libstd/vec.rs
	src/rt/rustrt.def.in
	src/test/run-pass/extern-pub.rs
This commit is contained in:
Brian Anderson 2013-07-02 17:36:58 -07:00
commit 1098d6980b
765 changed files with 23500 additions and 17316 deletions

View file

@ -12,13 +12,13 @@
use cast::transmute;
use container::Container;
use iterator::IteratorUtil;
use kinds::Copy;
use old_iter;
use old_iter::BaseIter;
use option::Option;
use sys;
use uint;
use vec;
use vec::ImmutableVector;
/// Code for dealing with @-vectors. This is pretty incomplete, and
/// contains a bunch of duplication from the code for ~-vectors.
@ -91,9 +91,9 @@ pub fn build_sized_opt<A>(size: Option<uint>,
/// Iterates over the `rhs` vector, copying each element and appending it to the
/// `lhs`. Afterwards, the `lhs` is then returned for use again.
#[inline]
pub fn append<T:Copy>(lhs: @[T], rhs: &const [T]) -> @[T] {
pub fn append<T:Copy>(lhs: @[T], rhs: &[T]) -> @[T] {
do build_sized(lhs.len() + rhs.len()) |push| {
for lhs.each |x| { push(copy *x); }
for lhs.iter().advance |x| { push(copy *x); }
for uint::range(0, rhs.len()) |i| { push(copy rhs[i]); }
}
}
@ -102,7 +102,7 @@ pub fn append<T:Copy>(lhs: @[T], rhs: &const [T]) -> @[T] {
/// Apply a function to each element of a vector and return the results
pub fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
do build_sized(v.len()) |push| {
for v.each |elem| {
for v.iter().advance |elem| {
push(f(elem));
}
}
@ -114,7 +114,7 @@ pub fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
* Creates an immutable vector of size `n_elts` and initializes the elements
* to the value returned by the function `op`.
*/
pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> @[T] {
pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> @[T] {
do build_sized(n_elts) |push| {
let mut i: uint = 0u;
while i < n_elts { push(op(i)); i += 1u; }
@ -163,9 +163,9 @@ pub mod traits {
use kinds::Copy;
use ops::Add;
impl<'self,T:Copy> Add<&'self const [T],@[T]> for @[T] {
impl<'self,T:Copy> Add<&'self [T],@[T]> for @[T] {
#[inline]
fn add(&self, rhs: & &'self const [T]) -> @[T] {
fn add(&self, rhs: & &'self [T]) -> @[T] {
append(*self, (*rhs))
}
}
@ -176,15 +176,16 @@ pub mod traits {}
pub mod raw {
use at_vec::capacity;
use cast;
use cast::{transmute, transmute_copy};
use libc;
use ptr;
use sys;
use uint;
use unstable::intrinsics::{move_val_init};
use unstable::intrinsics;
use unstable::intrinsics::{move_val_init, TyDesc};
use vec;
use vec::UnboxedVecRepr;
use sys::TypeDesc;
pub type VecRepr = vec::raw::VecRepr;
pub type SliceRepr = vec::raw::SliceRepr;
@ -246,14 +247,16 @@ pub mod raw {
// Only make the (slow) call into the runtime if we have to
if capacity(*v) < n {
let ptr: *mut *mut VecRepr = transmute(v);
let ty = sys::get_type_desc::<T>();
let ty = intrinsics::get_tydesc::<T>();
// XXX transmute shouldn't be necessary
let ty = cast::transmute(ty);
return reserve_raw(ty, ptr, n);
}
}
// Implementation detail. Shouldn't be public
#[allow(missing_doc)]
pub fn reserve_raw(ty: *TypeDesc, ptr: *mut *mut VecRepr, n: uint) {
pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut VecRepr, n: uint) {
unsafe {
let size_in_bytes = n * (*ty).size;

View file

@ -22,7 +22,8 @@ A dynamic, mutable location.
Similar to a mutable option type, but friendlier.
*/
#[mutable]
#[mutable] // XXX remove after snap
#[no_freeze]
#[deriving(Clone, DeepClone, Eq)]
#[allow(missing_doc)]
pub struct Cell<T> {

View file

@ -11,12 +11,12 @@
//! Utilities for manipulating the char type
use option::{None, Option, Some};
use str;
use str::{StrSlice, OwnedStr};
use u32;
use uint;
use int;
use str::StrSlice;
use unicode::{derived_property, general_category};
#[cfg(test)] use str::OwnedStr;
#[cfg(not(test))] use cmp::{Eq, Ord};
#[cfg(not(test))] use num::Zero;
@ -201,21 +201,21 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`
/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`
///
pub fn escape_unicode(c: char) -> ~str {
let s = u32::to_str_radix(c as u32, 16u);
let (c, pad) = cond!(
(c <= '\xff') { ('x', 2u) }
(c <= '\uffff') { ('u', 4u) }
_ { ('U', 8u) }
pub fn escape_unicode(c: char, f: &fn(char)) {
// avoid calling str::to_str_radix because we don't really need to allocate
// here.
f('\\');
let pad = cond!(
(c <= '\xff') { f('x'); 2 }
(c <= '\uffff') { f('u'); 4 }
_ { f('U'); 8 }
);
assert!(s.len() <= pad);
let mut out = ~"\\";
out.push_str(str::from_char(c));
for uint::range(s.len(), pad) |_| {
out.push_str("0");
for int::range_step(4 * (pad - 1), -1, -4) |offset| {
match ((c as u32) >> offset) & 0xf {
i @ 0 .. 9 => { f('0' + i as char); }
i => { f('a' + (i - 10) as char); }
}
}
out.push_str(s);
out
}
///
@ -230,16 +230,16 @@ pub fn escape_unicode(c: char) -> ~str {
/// - Any other chars in the range [0x20,0x7e] are not escaped.
/// - Any other chars are given hex unicode escapes; see `escape_unicode`.
///
pub fn escape_default(c: char) -> ~str {
pub fn escape_default(c: char, f: &fn(char)) {
match c {
'\t' => ~"\\t",
'\r' => ~"\\r",
'\n' => ~"\\n",
'\\' => ~"\\\\",
'\'' => ~"\\'",
'"' => ~"\\\"",
'\x20' .. '\x7e' => str::from_char(c),
_ => c.escape_unicode(),
'\t' => { f('\\'); f('t'); }
'\r' => { f('\\'); f('r'); }
'\n' => { f('\\'); f('n'); }
'\\' => { f('\\'); f('\\'); }
'\'' => { f('\\'); f('\''); }
'"' => { f('\\'); f('"'); }
'\x20' .. '\x7e' => { f(c); }
_ => c.escape_unicode(f),
}
}
@ -273,8 +273,8 @@ pub trait Char {
fn is_digit_radix(&self, radix: uint) -> bool;
fn to_digit(&self, radix: uint) -> Option<uint>;
fn from_digit(num: uint, radix: uint) -> Option<char>;
fn escape_unicode(&self) -> ~str;
fn escape_default(&self) -> ~str;
fn escape_unicode(&self, f: &fn(char));
fn escape_default(&self, f: &fn(char));
fn len_utf8_bytes(&self) -> uint;
}
@ -301,9 +301,9 @@ impl Char for char {
fn from_digit(num: uint, radix: uint) -> Option<char> { from_digit(num, radix) }
fn escape_unicode(&self) -> ~str { escape_unicode(*self) }
fn escape_unicode(&self, f: &fn(char)) { escape_unicode(*self, f) }
fn escape_default(&self) -> ~str { escape_default(*self) }
fn escape_default(&self, f: &fn(char)) { escape_default(*self, f) }
fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) }
}
@ -391,27 +391,37 @@ fn test_is_digit() {
#[test]
fn test_escape_default() {
assert_eq!('\n'.escape_default(), ~"\\n");
assert_eq!('\r'.escape_default(), ~"\\r");
assert_eq!('\''.escape_default(), ~"\\'");
assert_eq!('"'.escape_default(), ~"\\\"");
assert_eq!(' '.escape_default(), ~" ");
assert_eq!('a'.escape_default(), ~"a");
assert_eq!('~'.escape_default(), ~"~");
assert_eq!('\x00'.escape_default(), ~"\\x00");
assert_eq!('\x1f'.escape_default(), ~"\\x1f");
assert_eq!('\x7f'.escape_default(), ~"\\x7f");
assert_eq!('\xff'.escape_default(), ~"\\xff");
assert_eq!('\u011b'.escape_default(), ~"\\u011b");
assert_eq!('\U0001d4b6'.escape_default(), ~"\\U0001d4b6");
fn string(c: char) -> ~str {
let mut result = ~"";
do escape_default(c) |c| { result.push_char(c); }
return result;
}
assert_eq!(string('\n'), ~"\\n");
assert_eq!(string('\r'), ~"\\r");
assert_eq!(string('\''), ~"\\'");
assert_eq!(string('"'), ~"\\\"");
assert_eq!(string(' '), ~" ");
assert_eq!(string('a'), ~"a");
assert_eq!(string('~'), ~"~");
assert_eq!(string('\x00'), ~"\\x00");
assert_eq!(string('\x1f'), ~"\\x1f");
assert_eq!(string('\x7f'), ~"\\x7f");
assert_eq!(string('\xff'), ~"\\xff");
assert_eq!(string('\u011b'), ~"\\u011b");
assert_eq!(string('\U0001d4b6'), ~"\\U0001d4b6");
}
#[test]
fn test_escape_unicode() {
assert_eq!('\x00'.escape_unicode(), ~"\\x00");
assert_eq!('\n'.escape_unicode(), ~"\\x0a");
assert_eq!(' '.escape_unicode(), ~"\\x20");
assert_eq!('a'.escape_unicode(), ~"\\x61");
assert_eq!('\u011b'.escape_unicode(), ~"\\u011b");
assert_eq!('\U0001d4b6'.escape_unicode(), ~"\\U0001d4b6");
fn string(c: char) -> ~str {
let mut result = ~"";
do escape_unicode(c) |c| { result.push_char(c); }
return result;
}
assert_eq!(string('\x00'), ~"\\x00");
assert_eq!(string('\n'), ~"\\x0a");
assert_eq!(string(' '), ~"\\x20");
assert_eq!(string('a'), ~"\\x61");
assert_eq!(string('\u011b'), ~"\\u011b");
assert_eq!(string('\U0001d4b6'), ~"\\U0001d4b6");
}

View file

@ -10,17 +10,13 @@
#[doc(hidden)];
use libc::{c_char, c_void, intptr_t, uintptr_t};
use ptr::mut_null;
use libc::c_void;
use ptr::{mut_null};
use repr::BoxRepr;
use rt;
use rt::OldTaskContext;
use sys::TypeDesc;
use cast::transmute;
use unstable::intrinsics::TyDesc;
#[cfg(not(test))] use ptr::to_unsafe_ptr;
type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
type DropGlue<'self> = &'self fn(**TyDesc, *c_void);
/*
* Box annihilation
@ -63,6 +59,8 @@ unsafe fn each_live_alloc(read_next_before: bool,
#[cfg(unix)]
fn debug_mem() -> bool {
use rt;
use rt::OldTaskContext;
// XXX: Need to port the environment struct to newsched
match rt::context() {
OldTaskContext => ::rt::env::get().debug_mem,
@ -75,6 +73,19 @@ fn debug_mem() -> bool {
false
}
#[inline]
#[cfg(not(stage0))]
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
// This function should be inlined when stage0 is gone
((*tydesc).drop_glue)(data);
}
#[inline]
#[cfg(stage0)]
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
((*tydesc).drop_glue)(0 as **TyDesc, data);
}
/// Destroys all managed memory (i.e. @ boxes) held by the current task.
pub unsafe fn annihilate() {
use rt::local_heap::local_free;
@ -115,9 +126,9 @@ pub unsafe fn annihilate() {
// callback, as the original value may have been freed.
for each_live_alloc(false) |box, uniq| {
if !uniq {
let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
drop_glue(&tydesc, transmute(&(*box).data));
let tydesc: *TyDesc = transmute(copy (*box).header.type_desc);
let data = transmute(&(*box).data);
call_drop_glue(tydesc, data);
}
}

View file

@ -22,7 +22,7 @@ by convention implementing the `Clone` trait and calling the
*/
use core::kinds::Const;
use core::kinds::Freeze;
/// A common trait for cloning an object.
pub trait Clone {
@ -56,6 +56,18 @@ impl<'self, T> Clone for &'self T {
fn clone(&self) -> &'self T { *self }
}
impl<'self, T> Clone for &'self [T] {
/// Return a shallow copy of the slice.
#[inline]
fn clone(&self) -> &'self [T] { *self }
}
impl<'self> Clone for &'self str {
/// Return a shallow copy of the slice.
#[inline]
fn clone(&self) -> &'self str { *self }
}
macro_rules! clone_impl(
($t:ty) => {
impl Clone for $t {
@ -100,17 +112,17 @@ impl<T: DeepClone> DeepClone for ~T {
fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
}
// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
impl<T: Const + DeepClone> DeepClone for @T {
/// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone> DeepClone for @T {
/// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
/// a deep clone of a potentially cyclical type.
#[inline]
fn deep_clone(&self) -> @T { @(**self).deep_clone() }
}
// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
impl<T: Const + DeepClone> DeepClone for @mut T {
/// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone> DeepClone for @mut T {
/// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
/// a deep clone of a potentially cyclical type.
#[inline]
fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }

View file

@ -17,7 +17,7 @@ Message passing
use cast::{transmute, transmute_mut};
use container::Container;
use either::{Either, Left, Right};
use kinds::Owned;
use kinds::Send;
use option::{Option, Some, None};
use uint;
use vec::OwnedVector;
@ -77,7 +77,7 @@ pub struct Port<T> {
These allow sending or receiving an unlimited number of messages.
*/
pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
let (port, chan) = match rt::context() {
rt::OldTaskContext => match pipesy::stream() {
(p, c) => (Left(p), Left(c))
@ -91,7 +91,7 @@ pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
return (port, chan);
}
impl<T: Owned> GenericChan<T> for Chan<T> {
impl<T: Send> GenericChan<T> for Chan<T> {
fn send(&self, x: T) {
match self.inner {
Left(ref chan) => chan.send(x),
@ -100,7 +100,7 @@ impl<T: Owned> GenericChan<T> for Chan<T> {
}
}
impl<T: Owned> GenericSmartChan<T> for Chan<T> {
impl<T: Send> GenericSmartChan<T> for Chan<T> {
fn try_send(&self, x: T) -> bool {
match self.inner {
Left(ref chan) => chan.try_send(x),
@ -109,7 +109,7 @@ impl<T: Owned> GenericSmartChan<T> for Chan<T> {
}
}
impl<T: Owned> GenericPort<T> for Port<T> {
impl<T: Send> GenericPort<T> for Port<T> {
fn recv(&self) -> T {
match self.inner {
Left(ref port) => port.recv(),
@ -125,7 +125,7 @@ impl<T: Owned> GenericPort<T> for Port<T> {
}
}
impl<T: Owned> Peekable<T> for Port<T> {
impl<T: Send> Peekable<T> for Port<T> {
fn peek(&self) -> bool {
match self.inner {
Left(ref port) => port.peek(),
@ -134,7 +134,7 @@ impl<T: Owned> Peekable<T> for Port<T> {
}
}
impl<T: Owned> Selectable for Port<T> {
impl<T: Send> Selectable for Port<T> {
fn header(&mut self) -> *mut PacketHeader {
match self.inner {
Left(ref mut port) => port.header(),
@ -149,7 +149,7 @@ pub struct PortSet<T> {
ports: ~[pipesy::Port<T>],
}
impl<T: Owned> PortSet<T> {
impl<T: Send> PortSet<T> {
pub fn new() -> PortSet<T> {
PortSet {
ports: ~[]
@ -175,7 +175,7 @@ impl<T: Owned> PortSet<T> {
}
}
impl<T:Owned> GenericPort<T> for PortSet<T> {
impl<T:Send> GenericPort<T> for PortSet<T> {
fn try_recv(&self) -> Option<T> {
unsafe {
let self_ports = transmute_mut(&self.ports);
@ -204,7 +204,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
}
}
impl<T: Owned> Peekable<T> for PortSet<T> {
impl<T: Send> Peekable<T> for PortSet<T> {
fn peek(&self) -> bool {
// It'd be nice to use self.port.each, but that version isn't
// pure.
@ -223,7 +223,7 @@ pub struct SharedChan<T> {
inner: Either<Exclusive<pipesy::Chan<T>>, rtcomm::SharedChan<T>>
}
impl<T: Owned> SharedChan<T> {
impl<T: Send> SharedChan<T> {
/// Converts a `chan` into a `shared_chan`.
pub fn new(c: Chan<T>) -> SharedChan<T> {
let Chan { inner } = c;
@ -235,7 +235,7 @@ impl<T: Owned> SharedChan<T> {
}
}
impl<T: Owned> GenericChan<T> for SharedChan<T> {
impl<T: Send> GenericChan<T> for SharedChan<T> {
fn send(&self, x: T) {
match self.inner {
Left(ref chan) => {
@ -252,7 +252,7 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> {
}
}
impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
fn try_send(&self, x: T) -> bool {
match self.inner {
Left(ref chan) => {
@ -269,7 +269,7 @@ impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
}
}
impl<T: Owned> ::clone::Clone for SharedChan<T> {
impl<T: Send> ::clone::Clone for SharedChan<T> {
fn clone(&self) -> SharedChan<T> {
SharedChan { inner: self.inner.clone() }
}
@ -283,7 +283,7 @@ pub struct ChanOne<T> {
inner: Either<pipesy::ChanOne<T>, rtcomm::ChanOne<T>>
}
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
let (port, chan) = match rt::context() {
rt::OldTaskContext => match pipesy::oneshot() {
(p, c) => (Left(p), Left(c)),
@ -297,7 +297,7 @@ pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
return (port, chan);
}
impl<T: Owned> PortOne<T> {
impl<T: Send> PortOne<T> {
pub fn recv(self) -> T {
let PortOne { inner } = self;
match inner {
@ -315,7 +315,7 @@ impl<T: Owned> PortOne<T> {
}
}
impl<T: Owned> ChanOne<T> {
impl<T: Send> ChanOne<T> {
pub fn send(self, data: T) {
let ChanOne { inner } = self;
match inner {
@ -333,7 +333,7 @@ impl<T: Owned> ChanOne<T> {
}
}
pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
let PortOne { inner } = port;
match inner {
Left(p) => pipesy::recv_one(p),
@ -341,7 +341,7 @@ pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
}
}
pub fn try_recv_one<T: Owned>(port: PortOne<T>) -> Option<T> {
pub fn try_recv_one<T: Send>(port: PortOne<T>) -> Option<T> {
let PortOne { inner } = port;
match inner {
Left(p) => pipesy::try_recv_one(p),
@ -349,7 +349,7 @@ pub fn try_recv_one<T: Owned>(port: PortOne<T>) -> Option<T> {
}
}
pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
let ChanOne { inner } = chan;
match inner {
Left(c) => pipesy::send_one(c, data),
@ -357,7 +357,7 @@ pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
}
}
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
let ChanOne { inner } = chan;
match inner {
Left(c) => pipesy::try_send_one(c, data),
@ -367,7 +367,7 @@ pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
mod pipesy {
use kinds::Owned;
use kinds::Send;
use option::{Option, Some, None};
use pipes::{recv, try_recv, peek, PacketHeader};
use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable};
@ -375,17 +375,17 @@ mod pipesy {
use util::replace;
/*proto! oneshot (
Oneshot:send<T:Owned> {
Oneshot:send<T:Send> {
send(T) -> !
}
)*/
#[allow(non_camel_case_types)]
pub mod oneshot {
priv use core::kinds::Owned;
priv use core::kinds::Send;
use ptr::to_mut_unsafe_ptr;
pub fn init<T: Owned>() -> (server::Oneshot<T>, client::Oneshot<T>) {
pub fn init<T: Send>() -> (server::Oneshot<T>, client::Oneshot<T>) {
pub use core::pipes::HasBuffer;
let buffer = ~::core::pipes::Buffer {
@ -409,10 +409,10 @@ mod pipesy {
#[allow(non_camel_case_types)]
pub mod client {
priv use core::kinds::Owned;
priv use core::kinds::Send;
#[allow(non_camel_case_types)]
pub fn try_send<T: Owned>(pipe: Oneshot<T>, x_0: T) ->
pub fn try_send<T: Send>(pipe: Oneshot<T>, x_0: T) ->
::core::option::Option<()> {
{
use super::send;
@ -424,7 +424,7 @@ mod pipesy {
}
#[allow(non_camel_case_types)]
pub fn send<T: Owned>(pipe: Oneshot<T>, x_0: T) {
pub fn send<T: Send>(pipe: Oneshot<T>, x_0: T) {
{
use super::send;
let message = send(x_0);
@ -474,12 +474,12 @@ mod pipesy {
}
/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
let (port, chan) = oneshot::init();
(PortOne::new(port), ChanOne::new(chan))
}
impl<T: Owned> PortOne<T> {
impl<T: Send> PortOne<T> {
pub fn recv(self) -> T { recv_one(self) }
pub fn try_recv(self) -> Option<T> { try_recv_one(self) }
pub fn unwrap(self) -> oneshot::server::Oneshot<T> {
@ -489,7 +489,7 @@ mod pipesy {
}
}
impl<T: Owned> ChanOne<T> {
impl<T: Send> ChanOne<T> {
pub fn send(self, data: T) { send_one(self, data) }
pub fn try_send(self, data: T) -> bool { try_send_one(self, data) }
pub fn unwrap(self) -> oneshot::client::Oneshot<T> {
@ -503,7 +503,7 @@ mod pipesy {
* Receive a message from a oneshot pipe, failing if the connection was
* closed.
*/
pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
match port {
PortOne { contents: port } => {
let oneshot::send(message) = recv(port);
@ -513,7 +513,7 @@ mod pipesy {
}
/// Receive a message from a oneshot pipe unless the connection was closed.
pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
pub fn try_recv_one<T: Send> (port: PortOne<T>) -> Option<T> {
match port {
PortOne { contents: port } => {
let message = try_recv(port);
@ -529,7 +529,7 @@ mod pipesy {
}
/// Send a message on a oneshot pipe, failing if the connection was closed.
pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
match chan {
ChanOne { contents: chan } => oneshot::client::send(chan, data),
}
@ -539,7 +539,7 @@ mod pipesy {
* Send a message on a oneshot pipe, or return false if the connection was
* closed.
*/
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
match chan {
ChanOne { contents: chan } => {
oneshot::client::try_send(chan, data).is_some()
@ -550,16 +550,16 @@ mod pipesy {
// Streams - Make pipes a little easier in general.
/*proto! streamp (
Open:send<T: Owned> {
Open:send<T: Send> {
data(T) -> Open<T>
}
)*/
#[allow(non_camel_case_types)]
pub mod streamp {
priv use core::kinds::Owned;
priv use core::kinds::Send;
pub fn init<T: Owned>() -> (server::Open<T>, client::Open<T>) {
pub fn init<T: Send>() -> (server::Open<T>, client::Open<T>) {
pub use core::pipes::HasBuffer;
::core::pipes::entangle()
}
@ -569,10 +569,10 @@ mod pipesy {
#[allow(non_camel_case_types)]
pub mod client {
priv use core::kinds::Owned;
priv use core::kinds::Send;
#[allow(non_camel_case_types)]
pub fn try_data<T: Owned>(pipe: Open<T>, x_0: T) ->
pub fn try_data<T: Send>(pipe: Open<T>, x_0: T) ->
::core::option::Option<Open<T>> {
{
use super::data;
@ -585,7 +585,7 @@ mod pipesy {
}
#[allow(non_camel_case_types)]
pub fn data<T: Owned>(pipe: Open<T>, x_0: T) -> Open<T> {
pub fn data<T: Send>(pipe: Open<T>, x_0: T) -> Open<T> {
{
use super::data;
let (s, c) = ::core::pipes::entangle();
@ -623,7 +623,7 @@ mod pipesy {
These allow sending or receiving an unlimited number of messages.
*/
pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
let (s, c) = streamp::init();
(Port {
@ -633,7 +633,7 @@ mod pipesy {
})
}
impl<T: Owned> GenericChan<T> for Chan<T> {
impl<T: Send> GenericChan<T> for Chan<T> {
#[inline]
fn send(&self, x: T) {
unsafe {
@ -644,7 +644,7 @@ mod pipesy {
}
}
impl<T: Owned> GenericSmartChan<T> for Chan<T> {
impl<T: Send> GenericSmartChan<T> for Chan<T> {
#[inline]
fn try_send(&self, x: T) -> bool {
unsafe {
@ -661,7 +661,7 @@ mod pipesy {
}
}
impl<T: Owned> GenericPort<T> for Port<T> {
impl<T: Send> GenericPort<T> for Port<T> {
#[inline]
fn recv(&self) -> T {
unsafe {
@ -689,7 +689,7 @@ mod pipesy {
}
}
impl<T: Owned> Peekable<T> for Port<T> {
impl<T: Send> Peekable<T> for Port<T> {
#[inline]
fn peek(&self) -> bool {
unsafe {
@ -705,7 +705,7 @@ mod pipesy {
}
}
impl<T: Owned> Selectable for Port<T> {
impl<T: Send> Selectable for Port<T> {
fn header(&mut self) -> *mut PacketHeader {
match self.endp {
Some(ref mut endp) => endp.header(),
@ -733,15 +733,15 @@ pub fn select2i<A:Selectable, B:Selectable>(a: &mut A, b: &mut B)
}
/// Receive a message from one of two endpoints.
pub trait Select2<T: Owned, U: Owned> {
pub trait Select2<T: Send, U: Send> {
/// Receive a message or return `None` if a connection closes.
fn try_select(&mut self) -> Either<Option<T>, Option<U>>;
/// Receive a message or fail if a connection closes.
fn select(&mut self) -> Either<T, U>;
}
impl<T:Owned,
U:Owned,
impl<T:Send,
U:Send,
Left:Selectable + GenericPort<T>,
Right:Selectable + GenericPort<U>>
Select2<T, U>

View file

@ -90,7 +90,7 @@ struct Guard<'self, T, U> {
#[unsafe_destructor]
impl<'self, T, U> Drop for Guard<'self, T, U> {
fn finalize(&self) {
fn drop(&self) {
unsafe {
debug!("Guard: popping handler from TLS");
let curr = local_data_pop(self.cond.key);

View file

@ -34,18 +34,6 @@ pub trait Map<K, V>: Mutable {
/// Return true if the map contains a value for the specified key
fn contains_key(&self, key: &K) -> bool;
/// Visits all keys and values
fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool) -> bool;
/// Visit all keys
fn each_key(&self, f: &fn(&K) -> bool) -> bool;
/// Visit all values
fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool;
/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool;
/// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, key: &K) -> Option<&'a V>;

View file

@ -15,11 +15,11 @@
use container::Container;
use cmp::Eq;
use kinds::Copy;
use old_iter::BaseIter;
use iterator::IteratorUtil;
use result::Result;
use result;
use vec;
use vec::OwnedVector;
use vec::{OwnedVector, ImmutableVector};
/// The either type
#[deriving(Clone, Eq)]
@ -45,7 +45,7 @@ pub fn either<T, U, V>(f_left: &fn(&T) -> V,
/// Extracts from a vector of either all the left values
pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
do vec::build_sized(eithers.len()) |push| {
for eithers.each |elt| {
for eithers.iter().advance |elt| {
match *elt {
Left(ref l) => { push(copy *l); }
_ => { /* fallthrough */ }
@ -57,7 +57,7 @@ pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
/// Extracts from a vector of either all the right values
pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
do vec::build_sized(eithers.len()) |push| {
for eithers.each |elt| {
for eithers.iter().advance |elt| {
match *elt {
Right(ref r) => { push(copy *r); }
_ => { /* fallthrough */ }

View file

@ -40,12 +40,13 @@ with destructors.
use cast;
use container::{Map, Set};
use io;
use libc::{size_t, uintptr_t};
use libc::{uintptr_t};
use option::{None, Option, Some};
use ptr;
use hashmap::HashSet;
use stackwalk::walk_stack;
use sys;
use unstable::intrinsics::{TyDesc};
pub use stackwalk::Word;
@ -58,17 +59,11 @@ pub struct StackSegment {
}
pub mod rustrt {
use libc::size_t;
use stackwalk::Word;
use super::StackSegment;
#[link_name = "rustrt"]
pub extern {
#[rust_stack]
pub unsafe fn rust_call_tydesc_glue(root: *Word,
tydesc: *Word,
field: size_t);
#[rust_stack]
pub unsafe fn rust_gc_metadata() -> *Word;
@ -125,7 +120,7 @@ unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
return None;
}
type Visitor<'self> = &'self fn(root: **Word, tydesc: *Word) -> bool;
type Visitor<'self> = &'self fn(root: **Word, tydesc: *TyDesc) -> bool;
// Walks the list of roots for the given safe point, and calls visitor
// on each root.
@ -139,7 +134,7 @@ unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
let stack_roots: *u32 = bump(sp_meta, 2);
let reg_roots: *u8 = bump(stack_roots, num_stack_roots);
let addrspaces: *Word = align_to_pointer(bump(reg_roots, num_reg_roots));
let tydescs: ***Word = bump(addrspaces, num_stack_roots);
let tydescs: ***TyDesc = bump(addrspaces, num_stack_roots);
// Stack roots
let mut sri = 0;
@ -321,6 +316,19 @@ fn expect_sentinel() -> bool { true }
#[cfg(nogc)]
fn expect_sentinel() -> bool { false }
#[inline]
#[cfg(not(stage0))]
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
// This function should be inlined when stage0 is gone
((*tydesc).drop_glue)(data);
}
#[inline]
#[cfg(stage0)]
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
((*tydesc).drop_glue)(0 as **TyDesc, data);
}
// Entry point for GC-based cleanup. Walks stack looking for exchange
// heap and stack allocations requiring drop, and runs all
// destructors.
@ -364,7 +372,7 @@ pub fn cleanup_stack_for_failure() {
// FIXME #4420: Destroy this box
// FIXME #4330: Destroy this box
} else {
rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
call_drop_glue(tydesc, *root as *i8);
}
}
}

View file

@ -22,10 +22,12 @@
#[allow(missing_doc)];
use container::Container;
use old_iter::BaseIter;
use iterator::IteratorUtil;
use rt::io::Writer;
use str::OwnedStr;
use to_bytes::IterBytes;
use uint;
use vec::ImmutableVector;
// Alias `SipState` to `State`.
pub use State = hash::SipState;
@ -367,8 +369,8 @@ impl Streaming for SipState {
fn result_str(&mut self) -> ~str {
let r = self.result_bytes();
let mut s = ~"";
for r.each |b| {
s += uint::to_str_radix(*b as uint, 16u);
for r.iter().advance |b| {
s.push_str(uint::to_str_radix(*b as uint, 16u));
}
s
}
@ -469,8 +471,8 @@ mod tests {
fn to_hex_str(r: &[u8, ..8]) -> ~str {
let mut s = ~"";
for (*r).each |b| {
s += uint::to_str_radix(*b as uint, 16u);
for r.iter().advance |b| {
s.push_str(uint::to_str_radix(*b as uint, 16u));
}
s
}
@ -491,7 +493,7 @@ mod tests {
assert!(f == i && f == v);
buf += [t as u8];
buf.push(t as u8);
stream_inc.input([t as u8]);
t += 1;

View file

@ -18,14 +18,13 @@
use container::{Container, Mutable, Map, Set};
use cmp::{Eq, Equiv};
use hash::Hash;
use old_iter::BaseIter;
use old_iter;
use iterator::{IteratorUtil};
use iterator::{Iterator, IteratorUtil};
use option::{None, Option, Some};
use rand::RngUtil;
use rand;
use uint;
use vec;
use vec::{ImmutableVector, MutableVector};
use kinds::Copy;
use util::{replace, unreachable};
@ -283,10 +282,10 @@ impl<K:Hash + Eq,V> HashMap<K, V> {
impl<K:Hash + Eq,V> Container for HashMap<K, V> {
/// Return the number of elements in the map
fn len(&const self) -> uint { self.size }
fn len(&self) -> uint { self.size }
/// Return true if the map contains no elements
fn is_empty(&const self) -> bool { self.len() == 0 }
fn is_empty(&self) -> bool { self.len() == 0 }
}
impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
@ -308,41 +307,6 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
}
}
/// Visit all key-value pairs
fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
for self.buckets.each |bucket| {
for bucket.iter().advance |pair| {
if !blk(&pair.key, &pair.value) {
return false;
}
}
}
return true;
}
/// Visit all keys
fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
self.each(|k, _| blk(k))
}
/// Visit all values
fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
self.each(|_, v| blk(v))
}
/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
for uint::range(0, self.buckets.len()) |i| {
match self.buckets[i] {
Some(Bucket{key: ref key, value: ref mut value, _}) => {
if !blk(key, value) { return false; }
}
None => ()
}
}
return true;
}
/// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
match self.bucket_for_key(k) {
@ -523,6 +487,42 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
TableFull | FoundHole(_) => None,
}
}
/// Visit all keys
pub fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
self.iter().advance(|(k, _)| blk(k))
}
/// Visit all values
pub fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
self.iter().advance(|(_, v)| blk(v))
}
/// Iterate over the map and mutate the contained values
pub fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
for uint::range(0, self.buckets.len()) |i| {
match self.buckets[i] {
Some(Bucket{key: ref key, value: ref mut value, _}) => {
if !blk(key, value) { return false; }
}
None => ()
}
}
return true;
}
/// An iterator visiting all key-value pairs in arbitrary order.
/// Iterator element type is (&'a K, &'a V).
pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
HashMapIterator { iter: self.buckets.iter() }
}
/// An iterator visiting all key-value pairs in arbitrary order,
/// with mutable references to the values.
/// Iterator element type is (&'a K, &'a mut V).
pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
HashMapMutIterator { iter: self.buckets.mut_iter() }
}
}
impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
@ -541,7 +541,7 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
fn eq(&self, other: &HashMap<K, V>) -> bool {
if self.len() != other.len() { return false; }
for self.each |key, value| {
for self.iter().advance |(key, value)| {
match other.find(key) {
None => return false,
Some(v) => if value != v { return false },
@ -554,6 +554,61 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
}
/// HashMap iterator
pub struct HashMapIterator<'self, K, V> {
priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
}
/// HashMap mutable values iterator
pub struct HashMapMutIterator<'self, K, V> {
priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
}
/// HashSet iterator
pub struct HashSetIterator<'self, K> {
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
}
impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'self K, &'self V)> {
for self.iter.advance |elt| {
match elt {
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
&None => {},
}
}
None
}
}
impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'self, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
for self.iter.advance |elt| {
match elt {
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
&None => {},
}
}
None
}
}
impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
#[inline]
fn next(&mut self) -> Option<&'self K> {
for self.iter.advance |elt| {
match elt {
&Some(ref bucket) => return Some(&bucket.key),
&None => {},
}
}
None
}
}
/// An implementation of a hash set using the underlying representation of a
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits.
@ -561,12 +616,6 @@ pub struct HashSet<T> {
priv map: HashMap<T, ()>
}
impl<T:Hash + Eq> BaseIter<T> for HashSet<T> {
/// Visit all values in order
fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) }
fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl<T:Hash + Eq> Eq for HashSet<T> {
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
@ -574,10 +623,10 @@ impl<T:Hash + Eq> Eq for HashSet<T> {
impl<T:Hash + Eq> Container for HashSet<T> {
/// Return the number of elements in the set
fn len(&const self) -> uint { self.map.len() }
fn len(&self) -> uint { self.map.len() }
/// Return true if the set contains no elements
fn is_empty(&const self) -> bool { self.map.is_empty() }
fn is_empty(&self) -> bool { self.map.is_empty() }
}
impl<T:Hash + Eq> Mutable for HashSet<T> {
@ -600,12 +649,12 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
/// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
old_iter::all(self, |v| !other.contains(v))
self.iter().all(|v| !other.contains(v))
}
/// Return true if the set is a subset of another
fn is_subset(&self, other: &HashSet<T>) -> bool {
old_iter::all(self, |v| other.contains(v))
self.iter().all(|v| other.contains(v))
}
/// Return true if the set is a superset of another
@ -615,24 +664,25 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
/// Visit the values representing the difference
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
self.each(|v| other.contains(v) || f(v))
self.iter().advance(|v| other.contains(v) || f(v))
}
/// Visit the values representing the symmetric difference
fn symmetric_difference(&self,
other: &HashSet<T>,
f: &fn(&T) -> bool) -> bool {
self.difference(other, f) && other.difference(self, f)
self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
}
/// Visit the values representing the intersection
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
self.each(|v| !other.contains(v) || f(v))
self.iter().advance(|v| !other.contains(v) || f(v))
}
/// Visit the values representing the union
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
self.each(f) && other.each(|v| self.contains(v) || f(v))
self.iter().advance(|t| f(t)) &&
other.iter().advance(|v| self.contains(v) || f(v))
}
}
@ -663,6 +713,12 @@ impl<T:Hash + Eq> HashSet<T> {
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
self.map.contains_key_equiv(value)
}
/// An iterator visiting all elements in arbitrary order.
/// Iterator element type is &'a T.
pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
HashSetIterator { iter: self.map.buckets.iter() }
}
}
#[cfg(test)]
@ -807,7 +863,7 @@ mod test_map {
assert!(m.insert(i, i*2));
}
let mut observed = 0;
for m.each |k, v| {
for m.iter().advance |(k, v)| {
assert_eq!(*v, *k * 2);
observed |= (1 << *k);
}
@ -883,7 +939,8 @@ mod test_map {
mod test_set {
use super::*;
use container::{Container, Map, Set};
use vec;
use vec::ImmutableEqVector;
use uint;
#[test]
fn test_disjoint() {
@ -936,6 +993,19 @@ mod test_set {
assert!(b.is_superset(&a));
}
#[test]
fn test_iterate() {
let mut a = HashSet::new();
for uint::range(0, 32) |i| {
assert!(a.insert(i));
}
let mut observed = 0;
for a.iter().advance |k| {
observed |= (1 << *k);
}
assert_eq!(observed, 0xFFFF_FFFF);
}
#[test]
fn test_intersection() {
let mut a = HashSet::new();
@ -960,7 +1030,7 @@ mod test_set {
let mut i = 0;
let expected = [3, 5, 11, 77];
for a.intersection(&b) |x| {
assert!(vec::contains(expected, x));
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
@ -983,7 +1053,7 @@ mod test_set {
let mut i = 0;
let expected = [1, 5, 11];
for a.difference(&b) |x| {
assert!(vec::contains(expected, x));
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
@ -1009,7 +1079,7 @@ mod test_set {
let mut i = 0;
let expected = [-2, 1, 5, 11, 14, 22];
for a.symmetric_difference(&b) |x| {
assert!(vec::contains(expected, x));
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
@ -1039,7 +1109,7 @@ mod test_set {
let mut i = 0;
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
for a.union(&b) |x| {
assert!(vec::contains(expected, x));
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());

View file

@ -57,7 +57,7 @@ use os;
use cast;
use path::Path;
use ops::Drop;
use old_iter::{BaseIter, CopyableIter};
use iterator::IteratorUtil;
use ptr;
use result;
use str;
@ -65,7 +65,7 @@ use str::StrSlice;
use to_str::ToStr;
use uint;
use vec;
use vec::{OwnedVector, OwnedCopyableVector};
use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
#[allow(non_camel_case_types)] // not sure what to do about this
pub type fd_t = c_int;
@ -698,7 +698,7 @@ impl<T:Reader> ReaderUtil for T {
// over-read by reading 1-byte per char needed
nbread = if ncreq > nbreq { ncreq } else { nbreq };
if nbread > 0 {
bytes = vec::slice(bytes, offset, bytes.len()).to_vec();
bytes = bytes.slice(offset, bytes.len()).to_owned();
}
}
chars
@ -771,7 +771,9 @@ impl<T:Reader> ReaderUtil for T {
fn read_le_uint_n(&self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);
let mut (val, pos, i) = (0u64, 0, nbytes);
let mut val = 0u64;
let mut pos = 0;
let mut i = nbytes;
while i > 0 {
val += (self.read_u8() as u64) << pos;
pos += 8;
@ -787,7 +789,8 @@ impl<T:Reader> ReaderUtil for T {
fn read_be_uint_n(&self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);
let mut (val, i) = (0u64, nbytes);
let mut val = 0u64;
let mut i = nbytes;
while i > 0 {
i -= 1;
val += (self.read_u8() as u64) << i * 8;
@ -989,7 +992,7 @@ impl FILERes {
}
impl Drop for FILERes {
fn finalize(&self) {
fn drop(&self) {
unsafe {
libc::fclose(self.f);
}
@ -1042,16 +1045,18 @@ pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
// Byte readers
pub struct BytesReader<'self> {
bytes: &'self [u8],
pub struct BytesReader {
// FIXME(#5723) see other FIXME below
// FIXME(#7268) this should also be parameterized over <'self>
bytes: &'static [u8],
pos: @mut uint
}
impl<'self> Reader for BytesReader<'self> {
impl Reader for BytesReader {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
let count = uint::min(len, self.bytes.len() - *self.pos);
let view = vec::slice(self.bytes, *self.pos, self.bytes.len());
let view = self.bytes.slice(*self.pos, self.bytes.len());
vec::bytes::copy_memory(bytes, view, count);
*self.pos += count;
@ -1084,6 +1089,10 @@ impl<'self> Reader for BytesReader<'self> {
}
pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
// XXX XXX XXX this is glaringly unsound
// FIXME(#5723) Use a &Reader for the callback's argument. Should be:
// fn with_bytes_reader<'r, T>(bytes: &'r [u8], f: &fn(&'r Reader) -> T) -> T
let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
f(@BytesReader {
bytes: bytes,
pos: @mut 0
@ -1091,6 +1100,7 @@ pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
}
pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
// FIXME(#5723): As above.
with_bytes_reader(s.as_bytes(), f)
}
@ -1142,7 +1152,7 @@ impl<W:Writer,C> Writer for Wrapper<W, C> {
impl Writer for *libc::FILE {
fn write(&self, v: &[u8]) {
unsafe {
do vec::as_const_buf(v) |vbuf, len| {
do vec::as_imm_buf(v) |vbuf, len| {
let nout = libc::fwrite(vbuf as *c_void,
1,
len as size_t,
@ -1193,9 +1203,9 @@ impl Writer for fd_t {
fn write(&self, v: &[u8]) {
unsafe {
let mut count = 0u;
do vec::as_const_buf(v) |vbuf, len| {
do vec::as_imm_buf(v) |vbuf, len| {
while count < len {
let vb = ptr::const_offset(vbuf, count) as *c_void;
let vb = ptr::offset(vbuf, count) as *c_void;
let nout = libc::write(*self, vb, len as size_t);
if nout < 0 as ssize_t {
error!("error writing buffer");
@ -1234,7 +1244,7 @@ impl FdRes {
}
impl Drop for FdRes {
fn finalize(&self) {
fn drop(&self) {
unsafe {
libc::close(self.fd);
}
@ -1261,7 +1271,7 @@ pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
fn wb() -> c_int { O_WRONLY as c_int }
let mut fflags: c_int = wb();
for flags.each |f| {
for flags.iter().advance |f| {
match *f {
Append => fflags |= O_APPEND as c_int,
Create => fflags |= O_CREAT as c_int,
@ -1651,12 +1661,12 @@ impl Writer for BytesWriter {
let bytes = &mut *self.bytes;
let count = uint::max(bytes.len(), *self.pos + v_len);
vec::reserve(bytes, count);
bytes.reserve(count);
unsafe {
vec::raw::set_len(bytes, count);
let view = vec::mut_slice(*bytes, *self.pos, count);
let view = bytes.mut_slice(*self.pos, count);
vec::bytes::copy_memory(view, v, v_len);
}
@ -1772,7 +1782,7 @@ pub mod fsync {
#[unsafe_destructor]
impl<T:Copy> Drop for Res<T> {
fn finalize(&self) {
fn drop(&self) {
match self.arg.opt_level {
None => (),
Some(level) => {
@ -1902,8 +1912,9 @@ mod tests {
if len <= ivals.len() {
assert_eq!(res.len(), len);
}
assert!(vec::slice(ivals, 0u, res.len()) ==
vec::map(res, |x| *x as int));
for ivals.iter().zip(res.iter()).advance |(iv, c)| {
assert!(*iv == *c as int)
}
}
}
let mut i = 0;
@ -2015,7 +2026,7 @@ mod tests {
// write the ints to the file
{
let file = io::file_writer(&path, [io::Create]).get();
for uints.each |i| {
for uints.iter().advance |i| {
file.write_le_u64(*i);
}
}
@ -2023,7 +2034,7 @@ mod tests {
// then read them back and check that they are the same
{
let file = io::file_reader(&path).get();
for uints.each |i| {
for uints.iter().advance |i| {
assert_eq!(file.read_le_u64(), *i);
}
}
@ -2037,7 +2048,7 @@ mod tests {
// write the ints to the file
{
let file = io::file_writer(&path, [io::Create]).get();
for uints.each |i| {
for uints.iter().advance |i| {
file.write_be_u64(*i);
}
}
@ -2045,7 +2056,7 @@ mod tests {
// then read them back and check that they are the same
{
let file = io::file_reader(&path).get();
for uints.each |i| {
for uints.iter().advance |i| {
assert_eq!(file.read_be_u64(), *i);
}
}
@ -2059,7 +2070,7 @@ mod tests {
// write the ints to the file
{
let file = io::file_writer(&path, [io::Create]).get();
for ints.each |i| {
for ints.iter().advance |i| {
file.write_be_i32(*i);
}
}
@ -2067,7 +2078,7 @@ mod tests {
// then read them back and check that they are the same
{
let file = io::file_reader(&path).get();
for ints.each |i| {
for ints.iter().advance |i| {
// this tests that the sign extension is working
// (comparing the values as i32 would not test this)
assert_eq!(file.read_be_int_n(4), *i as i64);

View file

@ -56,7 +56,7 @@ pub trait FromIter<T> {
///
/// ~~~ {.rust}
/// let xs = ~[1, 2, 3];
/// let ys: ~[int] = do FromIter::from_iter |f| { xs.each(|x| f(*x)) };
/// 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;
@ -69,8 +69,8 @@ pub trait FromIter<T> {
*
* ~~~ {.rust}
* let xs = ~[1u, 2, 3, 4, 5];
* assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
* assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
* assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
* assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
* ~~~
*/
#[inline]
@ -109,7 +109,7 @@ pub fn all<T>(predicate: &fn(T) -> bool,
*
* ~~~ {.rust}
* let xs = ~[1u, 2, 3, 4, 5, 6];
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
* ~~~
*/
#[inline]
@ -130,7 +130,7 @@ pub fn find<T>(predicate: &fn(&T) -> bool,
*
* ~~~ {.rust}
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
* assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
* ~~~
*/
#[inline]
@ -156,7 +156,7 @@ pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
*
* ~~~ {.rust}
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
* assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5);
* ~~~
*/
#[inline]
@ -223,7 +223,7 @@ pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&m
*
* ~~~ {.rust}
* let xs: ~[int] = ~[1, 2, 3, 4];
* assert_eq!(do sum |f| { xs.each(f) }, 10);
* assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
* ~~~
*/
#[inline]
@ -238,7 +238,7 @@ pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
*
* ~~~ {.rust}
* let xs: ~[int] = ~[1, 2, 3, 4];
* assert_eq!(do product |f| { xs.each(f) }, 24);
* assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
* ~~~
*/
#[inline]
@ -257,15 +257,15 @@ mod tests {
#[test]
fn test_from_iter() {
let xs = ~[1, 2, 3];
let ys: ~[int] = do FromIter::from_iter |f| { xs.each(|x| f(*x)) };
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.each(f)));
assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
}
#[test]
@ -277,19 +277,19 @@ mod tests {
#[test]
fn test_find() {
let xs = ~[1u, 2, 3, 4, 5, 6];
assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
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.each(f)).unwrap(), &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.each(f)).unwrap(), &-5);
assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5);
}
#[test]
@ -300,24 +300,24 @@ mod tests {
#[test]
fn test_sum() {
let xs: ~[int] = ~[1, 2, 3, 4];
assert_eq!(do sum |f| { xs.each(f) }, 10);
assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
}
#[test]
fn test_empty_sum() {
let xs: ~[int] = ~[];
assert_eq!(do sum |f| { xs.each(f) }, 0);
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.each(f) }, 24);
assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
}
#[test]
fn test_empty_product() {
let xs: ~[int] = ~[];
assert_eq!(do product |f| { xs.each(f) }, 1);
assert_eq!(do product |f| { xs.iter().advance(f) }, 1);
}
}

View file

@ -17,20 +17,33 @@ implementing the `Iterator` trait.
*/
#[allow(default_methods)]; // solid enough for the use case here
use cmp;
use iter::{FromIter, Times};
use iter::Times;
use num::{Zero, One};
use option::{Option, Some, None};
use ops::{Add, Mul};
use cmp::Ord;
use clone::Clone;
/// Conversion from an `Iterator`
pub trait FromIterator<A, T: Iterator<A>> {
/// Build a container with elements from an external iterator.
pub fn from_iterator(iterator: &mut T) -> Self;
}
/// An interface for dealing with "external iterators". These types of iterators
/// can be resumed at any time as all state is stored internally as opposed to
/// being located on the call stack.
pub trait Iterator<A> {
/// Advance the iterator and return the next value. Return `None` when the end is reached.
fn next(&mut self) -> Option<A>;
/// Return a lower bound and upper bound on the remaining length of the iterator.
///
/// The common use case for the estimate is pre-allocating space to store the results.
fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
}
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
@ -72,8 +85,7 @@ pub trait IteratorUtil<A> {
// FIXME: #5898: should be called map
/// Creates a new iterator which will apply the specified function to each
/// element returned by the first, yielding the mapped element instead. This
/// similar to the `vec::map` function.
/// element returned by the first, yielding the mapped element instead.
///
/// # Example
///
@ -212,6 +224,26 @@ pub trait IteratorUtil<A> {
fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
-> ScanIterator<'r, A, B, Self, St>;
/// Creates an iterator that maps each element to an iterator,
/// and yields the elements of the produced iterators
///
/// # Example
///
/// ~~~ {.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));
/// // Check that `it` has the same elements as `ys`
/// let mut i = 0;
/// for it.advance |x: uint| {
/// assert_eq!(x, ys[i]);
/// i += 1;
/// }
/// ~~~
// FIXME: #5898: should be called `flat_map`
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
-> FlatMapIterator<'r, A, B, Self, U>;
/// An adaptation of an external iterator to the for-loop protocol of rust.
///
/// # Example
@ -226,7 +258,7 @@ pub trait IteratorUtil<A> {
fn advance(&mut self, f: &fn(A) -> bool) -> bool;
/// Loops through the entire iterator, collecting all of the elements into
/// a container implementing `FromIter`.
/// a container implementing `FromIterator`.
///
/// # Example
///
@ -235,7 +267,7 @@ pub trait IteratorUtil<A> {
/// let b: ~[int] = a.iter().transform(|&x| x).collect();
/// assert!(a == b);
/// ~~~
fn collect<B: FromIter<A>>(&mut self) -> B;
fn collect<B: FromIterator<A, Self>>(&mut self) -> B;
/// Loops through `n` iterations, returning the `n`th element of the
/// iterator.
@ -273,6 +305,7 @@ pub trait IteratorUtil<A> {
/// ~~~
fn fold<B>(&mut self, start: B, f: &fn(B, A) -> B) -> B;
// FIXME: #5898: should be called len
/// Counts the number of elements in this iterator.
///
/// # Example
@ -280,10 +313,10 @@ pub trait IteratorUtil<A> {
/// ~~~ {.rust}
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert!(it.count() == 5);
/// assert!(it.count() == 0);
/// assert!(it.len_() == 5);
/// assert!(it.len_() == 0);
/// ~~~
fn count(&mut self) -> uint;
fn len_(&mut self) -> uint;
/// Tests whether the predicate holds true for all elements in the iterator.
///
@ -314,6 +347,29 @@ pub trait IteratorUtil<A> {
/// Return the index of the first element satisfying the specified predicate
fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
/// Count the number of elements satisfying the specified predicate
fn count(&mut self, predicate: &fn(A) -> bool) -> uint;
/// Return the element that gives the maximum value from the specfied function
///
/// # Example
///
/// ~~~ {.rust}
/// let xs = [-3, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
/// ~~~
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
/// Return the element that gives the minimum value from the specfied function
///
/// # Example
///
/// ~~~ {.rust}
/// let xs = [-3, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
/// ~~~
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
}
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
@ -379,6 +435,12 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
ScanIterator{iter: self, f: f, state: initial_state}
}
#[inline]
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
-> FlatMapIterator<'r, A, B, T, U> {
FlatMapIterator{iter: self, f: f, subiter: None }
}
/// A shim implementing the `for` loop iteration protocol for iterator objects
#[inline]
fn advance(&mut self, f: &fn(A) -> bool) -> bool {
@ -393,8 +455,8 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
}
#[inline]
fn collect<B: FromIter<A>>(&mut self) -> B {
FromIter::from_iter::<A, B>(|f| self.advance(f))
fn collect<B: FromIterator<A, T>>(&mut self) -> B {
FromIterator::from_iterator(self)
}
/// Return the `n`th item yielded by an iterator.
@ -432,7 +494,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
/// Count the number of items yielded by an iterator
#[inline]
fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
fn len_(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
#[inline]
fn all(&mut self, f: &fn(A) -> bool) -> bool {
@ -467,6 +529,45 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
}
None
}
#[inline]
fn count(&mut self, predicate: &fn(A) -> bool) -> uint {
let mut i = 0;
for self.advance |x| {
if predicate(x) { i += 1 }
}
i
}
#[inline]
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
self.fold(None, |max: Option<(A, B)>, x| {
let x_val = f(&x);
match max {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val > y_val {
Some((x, x_val))
} else {
Some((y, y_val))
}
}
}).map_consume(|(x, _)| x)
}
#[inline]
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
self.fold(None, |min: Option<(A, B)>, x| {
let x_val = f(&x);
match min {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val < y_val {
Some((x, x_val))
} else {
Some((y, y_val))
}
}
}).map_consume(|(x, _)| x)
}
}
/// A trait for iterators over elements which can be added together
@ -581,6 +682,26 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
self.b.next()
}
}
#[inline]
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
let (a_lower, a_upper) = self.a.size_hint();
let (b_lower, b_upper) = self.b.size_hint();
let lower = match (a_lower, b_lower) {
(Some(x), Some(y)) => Some(x + y),
(Some(x), None) => Some(x),
(None, Some(y)) => Some(y),
(None, None) => None
};
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) => Some(x + y),
_ => None
};
(lower, upper)
}
}
/// An iterator which iterates two other iterators simultaneously
@ -614,6 +735,11 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
_ => None
}
}
#[inline]
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
self.iter.size_hint()
}
}
/// An iterator which filters the elements of `iter` with `predicate`
@ -634,6 +760,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
}
None
}
#[inline]
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(None, upper) // can't know a lower bound, due to the predicate
}
}
/// An iterator which uses `f` to both filter and map elements from `iter`
@ -653,6 +785,12 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
}
None
}
#[inline]
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(None, upper) // can't know a lower bound, due to the predicate
}
}
/// An iterator which yields the current count and the element during iteration
@ -805,6 +943,34 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
}
}
/// An iterator that maps each element to an iterator,
/// and yields the elements of the produced iterators
///
// FIXME #6967: Dummy B parameter to get around type inference bug
pub struct FlatMapIterator<'self, A, B, T, U> {
priv iter: T,
priv f: &'self fn(A) -> U,
priv subiter: Option<U>,
}
impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
FlatMapIterator<'self, A, B, T, U> {
#[inline]
fn next(&mut self) -> Option<B> {
loop {
for self.subiter.mut_iter().advance |inner| {
for inner.advance |x| {
return Some(x)
}
}
match self.iter.next().map_consume(|x| (self.f)(x)) {
None => return None,
next => self.subiter = next,
}
}
}
}
/// An iterator which just modifies the contained state throughout iteration.
pub struct UnfoldrIterator<'self, A, St> {
priv f: &'self fn(&mut St) -> Option<A>,
@ -816,7 +982,7 @@ impl<'self, A, St> UnfoldrIterator<'self, A, St> {
/// Creates a new iterator with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the iterator
#[inline]
pub fn new<'a>(f: &'a fn(&mut St) -> Option<A>, initial_state: St)
pub fn new<'a>(initial_state: St, f: &'a fn(&mut St) -> Option<A>)
-> UnfoldrIterator<'a, A, St> {
UnfoldrIterator {
f: f,
@ -863,13 +1029,12 @@ mod tests {
use super::*;
use prelude::*;
use iter;
use uint;
#[test]
fn test_counter_from_iter() {
let mut it = Counter::new(0, 5).take_(10);
let xs: ~[int] = iter::FromIter::from_iter::<int, ~[int]>(|f| it.advance(f));
let xs: ~[int] = FromIterator::from_iterator(&mut it);
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
}
@ -983,6 +1148,19 @@ mod tests {
assert_eq!(i, ys.len());
}
#[test]
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 i = 0;
for it.advance |x: uint| {
assert_eq!(x, ys[i]);
i += 1;
}
assert_eq!(i, ys.len());
}
#[test]
fn test_unfoldr() {
fn count(st: &mut uint) -> Option<uint> {
@ -995,7 +1173,7 @@ mod tests {
}
}
let mut it = UnfoldrIterator::new(count, 0);
let mut it = UnfoldrIterator::new(0, count);
let mut i = 0;
for it.advance |counted| {
assert_eq!(counted, i);
@ -1020,11 +1198,11 @@ mod tests {
}
#[test]
fn test_iterator_count() {
fn test_iterator_len() {
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(v.slice(0, 4).iter().count(), 4);
assert_eq!(v.slice(0, 10).iter().count(), 10);
assert_eq!(v.slice(0, 0).iter().count(), 0);
assert_eq!(v.slice(0, 4).iter().len_(), 4);
assert_eq!(v.slice(0, 10).iter().len_(), 10);
assert_eq!(v.slice(0, 0).iter().len_(), 0);
}
#[test]
@ -1099,4 +1277,24 @@ mod tests {
assert_eq!(v.iter().position_(|x| *x % 3 == 0).unwrap(), 1);
assert!(v.iter().position_(|x| *x % 12 == 0).is_none());
}
#[test]
fn test_count() {
let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
assert_eq!(xs.iter().count(|x| *x == 2), 3);
assert_eq!(xs.iter().count(|x| *x == 5), 1);
assert_eq!(xs.iter().count(|x| *x == 95), 0);
}
#[test]
fn test_max_by() {
let xs = [-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
}
#[test]
fn test_min_by() {
let xs = [-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
}
}

View file

@ -24,11 +24,10 @@ The 4 kinds are
scalar types and managed pointers, and exludes owned pointers. It
also excludes types that implement `Drop`.
* Owned - owned types and types containing owned types. These types
* Send - owned types and types containing owned types. These types
may be transferred across task boundaries.
* Const - types that are deeply immutable. Const types are used for
freezable data structures.
* Freeze - types that are deeply immutable.
`Copy` types include both implicitly copyable types that the compiler
will copy automatically and non-implicitly copyable types that require
@ -44,14 +43,28 @@ pub trait Copy {
// Empty.
}
#[cfg(stage0)]
#[lang="owned"]
pub trait Owned {
// Empty.
pub trait Send {
// empty.
}
#[cfg(not(stage0))]
#[lang="send"]
pub trait Send {
// empty.
}
#[cfg(stage0)]
#[lang="const"]
pub trait Const {
// Empty.
pub trait Freeze {
// empty.
}
#[cfg(not(stage0))]
#[lang="freeze"]
pub trait Freeze {
// empty.
}
#[lang="sized"]

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,7 @@ use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handl
*
* These two cases aside, the interface is safe.
*/
pub type LocalDataKey<'self,T> = &'self fn(v: @T);
pub type LocalDataKey<'self,T> = &'self fn:Copy(v: @T);
/**
* Remove a task-local data value from the table, returning the
@ -92,14 +92,12 @@ fn test_tls_multitask() {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"parent data");
do task::spawn {
unsafe {
// TLS shouldn't carry over.
assert!(local_data_get(my_key).is_none());
local_data_set(my_key, @~"child data");
assert!(*(local_data_get(my_key).get()) ==
// TLS shouldn't carry over.
assert!(local_data_get(my_key).is_none());
local_data_set(my_key, @~"child data");
assert!(*(local_data_get(my_key).get()) ==
~"child data");
// should be cleaned up for us
}
// should be cleaned up for us
}
// Must work multiple times
assert!(*(local_data_get(my_key).get()) == ~"parent data");
@ -206,12 +204,11 @@ fn test_tls_cleanup_on_failure() {
local_data_set(str_key, @~"parent data");
local_data_set(box_key, @@());
do task::spawn {
unsafe { // spawn_linked
local_data_set(str_key, @~"string data");
local_data_set(box_key, @@());
local_data_set(int_key, @42);
fail!();
}
// spawn_linked
local_data_set(str_key, @~"string data");
local_data_set(box_key, @@());
local_data_set(int_key, @42);
fail!();
}
// Not quite nondeterministic.
local_data_set(int_key, @31337);

View file

@ -15,9 +15,8 @@ use ptr::to_unsafe_ptr;
#[cfg(not(test))] use cmp::{Eq, Ord};
pub mod raw {
use intrinsic::TyDesc;
use std::unstable::intrinsics::TyDesc;
pub static RC_EXCHANGE_UNIQUE : uint = (-1) as uint;
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
pub static RC_IMMORTAL : uint = 0x77777777;

View file

@ -754,8 +754,8 @@ impl Float for f32 {
///
#[inline]
pub fn to_str(num: f32) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -768,8 +768,8 @@ pub fn to_str(num: f32) -> ~str {
///
#[inline]
pub fn to_str_hex(num: f32) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 16u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -789,8 +789,8 @@ pub fn to_str_hex(num: f32) -> ~str {
///
#[inline]
pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
let (r, special) = strconv::to_str_common(
&num, rdx, true, strconv::SignNeg, strconv::DigAll);
let (r, special) = strconv::float_to_str_common(
num, rdx, true, strconv::SignNeg, strconv::DigAll);
if special { fail!("number has a special value, \
try to_str_radix_special() if those are expected") }
r
@ -807,7 +807,7 @@ pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
///
#[inline]
pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
strconv::to_str_common(&num, rdx, true,
strconv::float_to_str_common(num, rdx, true,
strconv::SignNeg, strconv::DigAll)
}
@ -822,8 +822,8 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
///
#[inline]
pub fn to_str_exact(num: f32, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
r
}
@ -838,8 +838,8 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str {
///
#[inline]
pub fn to_str_digits(num: f32, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
r
}

View file

@ -796,8 +796,8 @@ impl Float for f64 {
///
#[inline]
pub fn to_str(num: f64) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -810,8 +810,8 @@ pub fn to_str(num: f64) -> ~str {
///
#[inline]
pub fn to_str_hex(num: f64) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 16u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -831,8 +831,8 @@ pub fn to_str_hex(num: f64) -> ~str {
///
#[inline]
pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
let (r, special) = strconv::to_str_common(
&num, rdx, true, strconv::SignNeg, strconv::DigAll);
let (r, special) = strconv::float_to_str_common(
num, rdx, true, strconv::SignNeg, strconv::DigAll);
if special { fail!("number has a special value, \
try to_str_radix_special() if those are expected") }
r
@ -849,7 +849,7 @@ pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
///
#[inline]
pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
strconv::to_str_common(&num, rdx, true,
strconv::float_to_str_common(num, rdx, true,
strconv::SignNeg, strconv::DigAll)
}
@ -864,8 +864,8 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
///
#[inline]
pub fn to_str_exact(num: f64, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
r
}
@ -880,8 +880,8 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str {
///
#[inline]
pub fn to_str_digits(num: f64, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
r
}

View file

@ -101,8 +101,8 @@ pub mod consts {
///
#[inline]
pub fn to_str(num: float) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -115,8 +115,8 @@ pub fn to_str(num: float) -> ~str {
///
#[inline]
pub fn to_str_hex(num: float) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
let (r, _) = strconv::float_to_str_common(
num, 16u, true, strconv::SignNeg, strconv::DigAll);
r
}
@ -136,8 +136,8 @@ pub fn to_str_hex(num: float) -> ~str {
///
#[inline]
pub fn to_str_radix(num: float, radix: uint) -> ~str {
let (r, special) = strconv::to_str_common(
&num, radix, true, strconv::SignNeg, strconv::DigAll);
let (r, special) = strconv::float_to_str_common(
num, radix, true, strconv::SignNeg, strconv::DigAll);
if special { fail!("number has a special value, \
try to_str_radix_special() if those are expected") }
r
@ -154,7 +154,7 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str {
///
#[inline]
pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
strconv::to_str_common(&num, radix, true,
strconv::float_to_str_common(num, radix, true,
strconv::SignNeg, strconv::DigAll)
}
@ -169,8 +169,8 @@ pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
///
#[inline]
pub fn to_str_exact(num: float, digits: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigExact(digits));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(digits));
r
}
@ -185,8 +185,8 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str {
///
#[inline]
pub fn to_str_digits(num: float, digits: uint) -> ~str {
let (r, _) = strconv::to_str_common(
&num, 10u, true, strconv::SignNeg, strconv::DigMax(digits));
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(digits));
r
}

View file

@ -17,6 +17,7 @@ macro_rules! int_module (($T:ty, $bits:expr) => (mod generated {
use num::{ToStrRadix, FromStrRadix};
use num::{Zero, One, strconv};
use prelude::*;
use str;
pub use cmp::{min, max};
@ -400,7 +401,8 @@ impl Integer for $T {
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut (m, n) = (*self, *other);
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
@ -528,25 +530,33 @@ impl FromStrRadix for $T {
/// Convert to a string as a byte slice in a given base.
#[inline]
pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
let (buf, _) = strconv::to_str_bytes_common(&n, radix, false,
strconv::SignNeg, strconv::DigAll);
f(buf)
// The radix can be as low as 2, so we need at least 64 characters for a
// base 2 number, and then we need another for a possible '-' character.
let mut buf = [0u8, ..65];
let mut cur = 0;
do strconv::int_to_str_bytes_common(n, radix, strconv::SignNeg) |i| {
buf[cur] = i;
cur += 1;
}
f(buf.slice(0, cur))
}
/// Convert to a string in base 10.
#[inline]
pub fn to_str(num: $T) -> ~str {
let (buf, _) = strconv::to_str_common(&num, 10u, false,
strconv::SignNeg, strconv::DigAll);
buf
to_str_radix(num, 10u)
}
/// Convert to a string in a given base.
#[inline]
pub fn to_str_radix(num: $T, radix: uint) -> ~str {
let (buf, _) = strconv::to_str_common(&num, radix, false,
strconv::SignNeg, strconv::DigAll);
buf
let mut buf: ~[u8] = ~[];
do strconv::int_to_str_bytes_common(num, radix, strconv::SignNeg) |i| {
buf.push(i);
}
// We know we generated valid utf-8, so we don't need to go through that
// check.
unsafe { str::raw::from_bytes_owned(buf) }
}
impl ToStr for $T {

View file

@ -412,7 +412,7 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(radix: uint, pow
if my_pow % 2u == 1u {
total = total * multiplier;
}
my_pow = my_pow / 2u;
my_pow = my_pow / 2u;
multiplier = multiplier * multiplier;
}
total

View file

@ -16,13 +16,12 @@ use ops::{Add, Sub, Mul, Div, Rem, Neg};
use option::{None, Option, Some};
use char;
use str;
use str::{StrSlice};
use str::StrSlice;
use kinds::Copy;
use vec;
use vec::{CopyableVector, ImmutableVector};
use vec::{CopyableVector, ImmutableVector, MutableVector};
use vec::OwnedVector;
use num::{NumCast, Zero, One, cast, pow_with_uint};
use f64;
use num::{NumCast, Zero, One, cast, pow_with_uint, Integer};
use num::{Round, Float, FPNaN, FPInfinite};
pub enum ExponentFormat {
ExpNone,
@ -42,35 +41,6 @@ pub enum SignFormat {
SignAll
}
#[inline]
fn is_NaN<T:Eq>(num: &T) -> bool {
*num != *num
}
#[inline]
fn is_inf<T:Eq+NumStrConv>(num: &T) -> bool {
match NumStrConv::inf() {
None => false,
Some(n) => *num == n
}
}
#[inline]
fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool {
match NumStrConv::neg_inf() {
None => false,
Some(n) => *num == n
}
}
#[inline]
fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Div<T,T>>(num: &T) -> bool {
let _0: T = Zero::zero();
let _1: T = One::one();
*num == _0 && is_neg_inf(&(_1 / *num))
}
pub trait NumStrConv {
fn NaN() -> Option<Self>;
fn inf() -> Option<Self>;
@ -93,16 +63,9 @@ macro_rules! impl_NumStrConv_Floating (($t:ty) => (
fn neg_zero() -> Option<$t> { Some(-0.0 ) }
#[inline]
fn round_to_zero(&self) -> $t {
( if *self < 0.0 { f64::ceil(*self as f64) }
else { f64::floor(*self as f64) }
) as $t
}
fn round_to_zero(&self) -> $t { self.trunc() }
#[inline]
fn fractional_part(&self) -> $t {
*self - self.round_to_zero()
}
fn fractional_part(&self) -> $t { self.fract() }
}
))
@ -145,6 +108,87 @@ static negative_inf_buf: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8,
'f' as u8];
static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
/**
* Converts an integral number to its string representation as a byte vector.
* This is meant to be a common base implementation for all integral string
* conversion functions like `to_str()` or `to_str_radix()`.
*
* # Arguments
* - `num` - The number to convert. Accepts any number that
* implements the numeric traits.
* - `radix` - Base to use. Accepts only the values 2-36.
* - `sign` - How to emit the sign. Options are:
* - `SignNone`: No sign at all. Basically emits `abs(num)`.
* - `SignNeg`: Only `-` on negative values.
* - `SignAll`: Both `+` on positive, and `-` on negative numbers.
* - `f` - a callback which will be invoked for each ascii character
* which composes the string representation of this integer
*
* # Return value
* A tuple containing the byte vector, and a boolean flag indicating
* whether it represents a special value like `inf`, `-inf`, `NaN` or not.
* It returns a tuple because there can be ambiguity between a special value
* and a number representation at higher bases.
*
* # Failure
* - Fails if `radix` < 2 or `radix` > 36.
*/
pub fn int_to_str_bytes_common<T:NumCast+Zero+Eq+Ord+Integer+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
num: T, radix: uint, sign: SignFormat, f: &fn(u8)) {
assert!(2 <= radix && radix <= 36);
let _0: T = Zero::zero();
let neg = num < _0;
let radix_gen: T = cast(radix);
let mut deccum = num;
// This is just for integral types, the largest of which is a u64. The
// smallest base that we can have is 2, so the most number of digits we're
// ever going to have is 64
let mut buf = [0u8, ..64];
let mut cur = 0;
// Loop at least once to make sure at least a `0` gets emitted.
loop {
// Calculate the absolute value of each digit instead of only
// doing it once for the whole number because a
// representable negative number doesn't necessary have an
// representable additive inverse of the same type
// (See twos complement). But we assume that for the
// numbers [-35 .. 0] we always have [0 .. 35].
let current_digit_signed = deccum % radix_gen;
let current_digit = if current_digit_signed < _0 {
-current_digit_signed
} else {
current_digit_signed
};
buf[cur] = match current_digit.to_u8() {
i @ 0..9 => '0' as u8 + i,
i => 'a' as u8 + (i - 10),
};
cur += 1;
deccum = deccum / radix_gen;
// No more digits to calculate for the non-fractional part -> break
if deccum == _0 { break; }
}
// Decide what sign to put in front
match sign {
SignNeg | SignAll if neg => { f('-' as u8); }
SignAll => { f('+' as u8); }
_ => ()
}
// We built the number in reverse order, so un-reverse it here
while cur > 0 {
cur -= 1;
f(buf[cur]);
}
}
/**
* Converts a number to its string representation as a byte vector.
* This is meant to be a common base implementation for all numeric string
@ -176,44 +220,39 @@ static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
* # Failure
* - Fails if `radix` < 2 or `radix` > 36.
*/
pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
num: &T, radix: uint, negative_zero: bool,
num: T, radix: uint, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
if (radix as int) < 2 {
fail!("to_str_bytes_common: radix %? to low, must lie in the range [2, 36]", radix);
} else if radix as int > 36 {
fail!("to_str_bytes_common: radix %? to high, must lie in the range [2, 36]", radix);
}
assert!(2 <= radix && radix <= 36);
let _0: T = Zero::zero();
let _1: T = One::one();
if is_NaN(num) {
return ("NaN".as_bytes().to_owned(), true);
}
else if is_inf(num){
return match sign {
SignAll => ("+inf".as_bytes().to_owned(), true),
_ => ("inf".as_bytes().to_owned(), true)
match num.classify() {
FPNaN => { return ("NaN".as_bytes().to_owned(), true); }
FPInfinite if num > _0 => {
return match sign {
SignAll => ("+inf".as_bytes().to_owned(), true),
_ => ("inf".as_bytes().to_owned(), true)
};
}
}
else if is_neg_inf(num) {
return match sign {
SignNone => ("inf".as_bytes().to_owned(), true),
_ => ("-inf".as_bytes().to_owned(), true),
FPInfinite if num < _0 => {
return match sign {
SignNone => ("inf".as_bytes().to_owned(), true),
_ => ("-inf".as_bytes().to_owned(), true),
};
}
_ => {}
}
let neg = *num < _0 || (negative_zero && is_neg_zero(num));
let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
let mut buf: ~[u8] = ~[];
let radix_gen: T = cast(radix as int);
let mut deccum;
// First emit the non-fractional part, looping at least once to make
// sure at least a `0` gets emitted.
deccum = num.round_to_zero();
let mut deccum = num.trunc();
loop {
// Calculate the absolute value of each digit instead of only
// doing it once for the whole number because a
@ -221,16 +260,11 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
// representable additive inverse of the same type
// (See twos complement). But we assume that for the
// numbers [-35 .. 0] we always have [0 .. 35].
let current_digit_signed = deccum % radix_gen;
let current_digit = if current_digit_signed < _0 {
-current_digit_signed
} else {
current_digit_signed
};
let current_digit = (deccum % radix_gen).abs();
// Decrease the deccumulator one digit at a time
deccum = deccum / radix_gen;
deccum = deccum.round_to_zero();
deccum = deccum.trunc();
buf.push(char::from_digit(current_digit.to_int() as uint, radix)
.unwrap() as u8);
@ -257,7 +291,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
_ => ()
}
vec::reverse(buf);
buf.reverse();
// Remember start of the fractional digits.
// Points one beyond end of buf if none get generated,
@ -265,7 +299,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
let start_fractional_digits = buf.len();
// Now emit the fractional part, if any
deccum = num.fractional_part();
deccum = num.fract();
if deccum != _0 || (limit_digits && exact && digit_count > 0) {
buf.push('.' as u8);
let mut dig = 0u;
@ -286,18 +320,13 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
// Calculate the absolute value of each digit.
// See note in first loop.
let current_digit_signed = deccum.round_to_zero();
let current_digit = if current_digit_signed < _0 {
-current_digit_signed
} else {
current_digit_signed
};
let current_digit = deccum.trunc().abs();
buf.push(char::from_digit(
current_digit.to_int() as uint, radix).unwrap() as u8);
// Decrease the deccumulator one fractional digit at a time
deccum = deccum.fractional_part();
deccum = deccum.fract();
dig += 1u;
}
@ -382,11 +411,11 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
* `to_str_bytes_common()`, for details see there.
*/
#[inline]
pub fn to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
num: &T, radix: uint, negative_zero: bool,
pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+Round+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
num: T, radix: uint, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
let (bytes, special) = to_str_bytes_common(num, radix,
let (bytes, special) = float_to_str_bytes_common(num, radix,
negative_zero, sign, digits);
(str::from_bytes(bytes), special)
}

View file

@ -18,6 +18,7 @@ use num::BitCount;
use num::{ToStrRadix, FromStrRadix};
use num::{Zero, One, strconv};
use prelude::*;
use str;
pub use cmp::{min, max};
@ -237,7 +238,8 @@ impl Integer for $T {
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut (m, n) = (*self, *other);
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
@ -355,25 +357,33 @@ impl FromStrRadix for $T {
/// Convert to a string as a byte slice in a given base.
#[inline]
pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
let (buf, _) = strconv::to_str_bytes_common(&n, radix, false,
strconv::SignNeg, strconv::DigAll);
f(buf)
// The radix can be as low as 2, so we need at least 64 characters for a
// base 2 number.
let mut buf = [0u8, ..64];
let mut cur = 0;
do strconv::int_to_str_bytes_common(n, radix, strconv::SignNone) |i| {
buf[cur] = i;
cur += 1;
}
f(buf.slice(0, cur))
}
/// Convert to a string in base 10.
#[inline]
pub fn to_str(num: $T) -> ~str {
let (buf, _) = strconv::to_str_common(&num, 10u, false,
strconv::SignNeg, strconv::DigAll);
buf
to_str_radix(num, 10u)
}
/// Convert to a string in a given base.
#[inline]
pub fn to_str_radix(num: $T, radix: uint) -> ~str {
let (buf, _) = strconv::to_str_common(&num, radix, false,
strconv::SignNeg, strconv::DigAll);
buf
let mut buf = ~[];
do strconv::int_to_str_bytes_common(num, radix, strconv::SignNone) |i| {
buf.push(i);
}
// We know we generated valid utf-8, so we don't need to go through that
// check.
unsafe { str::raw::from_bytes_owned(buf) }
}
impl ToStr for $T {

View file

@ -1,296 +0,0 @@
// Copyright 2012-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.
/*!
**Deprecated** iteration traits and common implementations.
*/
#[allow(missing_doc)];
use cmp::{Eq};
use kinds::Copy;
use option::{None, Option, Some};
use vec;
/// A function used to initialize the elements of a sequence
pub type InitOp<'self,T> = &'self fn(uint) -> T;
pub trait BaseIter<A> {
fn each(&self, blk: &fn(v: &A) -> bool) -> bool;
fn size_hint(&self) -> Option<uint>;
}
pub trait ReverseIter<A>: BaseIter<A> {
fn each_reverse(&self, blk: &fn(&A) -> bool) -> bool;
}
pub trait ExtendedIter<A> {
fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool;
fn all(&self, blk: &fn(&A) -> bool) -> bool;
fn any(&self, blk: &fn(&A) -> bool) -> bool;
fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
}
pub trait EqIter<A:Eq> {
fn contains(&self, x: &A) -> bool;
fn count(&self, x: &A) -> uint;
}
pub trait CopyableIter<A:Copy> {
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
fn to_vec(&self) -> ~[A];
fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
}
// A trait for sequences that can be built by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
/**
* Builds a buildable sequence by calling a provided function with
* an argument function that pushes an element onto the back of
* the sequence.
* This version takes an initial size for the sequence.
*
* # Arguments
*
* * size - A hint for an initial size of the sequence
* * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
}
#[inline]
pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
let mut i = 0;
for this.each |a| {
if !blk(i, a) {
return false;
}
i += 1;
}
return true;
}
pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
_eachi(this, blk)
}
#[inline]
pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
for this.each |a| {
if !blk(a) {
return false;
}
}
return true;
}
#[inline]
pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
for this.each |a| {
if blk(a) {
return true;
}
}
return false;
}
#[inline]
pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA,
prd: &fn(&A) -> bool)
-> ~[A] {
do vec::build_sized_opt(this.size_hint()) |push| {
for this.each |a| {
if prd(a) { push(copy *a); }
}
}
}
#[inline]
pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] {
do vec::build_sized_opt(this.size_hint()) |push| {
for this.each |a| {
push(op(a));
}
}
}
#[inline]
pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA,
op: &fn(&A) -> IB)
-> ~[B] {
do vec::build |push| {
for this.each |a| {
for op(a).each |&b| {
push(b);
}
}
}
}
#[inline]
pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B)
-> B {
let mut b = b0;
for this.each |a| {
b = blk(&b, a);
}
b
}
#[inline]
pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] {
map_to_vec(this, |&x| x)
}
#[inline]
pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool {
for this.each |a| {
if *a == *x { return true; }
}
return false;
}
#[inline]
pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint {
do foldl(this, 0) |count, value| {
if *value == *x {
*count + 1
} else {
*count
}
}
}
#[inline]
pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
-> Option<uint> {
let mut i = 0;
for this.each |a| {
if f(a) { return Some(i); }
i += 1;
}
return None;
}
#[inline]
pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
-> Option<A> {
for this.each |i| {
if f(i) { return Some(copy *i) }
}
return None;
}
// Some functions for just building
/**
* Builds a sequence by calling a provided function with an argument
* function that pushes an element to the back of a sequence.
*
* # Arguments
*
* * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
#[inline]
pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
Buildable::build_sized(4, builder)
}
/**
* Builds a sequence by calling a provided function with an argument
* function that pushes an element to the back of the sequence.
* This version takes an initial size for the sequence.
*
* # Arguments
*
* * size - An option, maybe containing initial size of the sequence
* to reserve.
* * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
#[inline]
pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
builder: &fn(push: &fn(A))) -> B {
Buildable::build_sized(size.get_or_default(4), builder)
}
// Functions that combine iteration and building
/// Applies a function to each element of an iterable and returns the results
/// in a sequence built via `BU`. See also `map_to_vec`.
#[inline]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
-> BU {
do build_sized_opt(v.size_hint()) |push| {
for v.each() |elem| {
push(f(elem));
}
}
}
/**
* Creates and initializes a generic sequence from a function.
*
* Creates a generic sequence of size `n_elts` and initializes the elements
* to the value returned by the function `op`.
*/
#[inline]
pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
do Buildable::build_sized(n_elts) |push| {
let mut i: uint = 0u;
while i < n_elts { push(op(i)); i += 1u; }
}
}
/**
* Creates and initializes a generic sequence with some elements.
*
* Creates an immutable vector of size `n_elts` and initializes the elements
* to the value `t`.
*/
#[inline]
pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
do Buildable::build_sized(n_elts) |push| {
let mut i: uint = 0;
while i < n_elts { push(copy t); i += 1; }
}
}
/// Appends two generic sequences.
#[inline]
pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
-> BT {
let size_opt = lhs.size_hint().chain_ref(
|sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
do build_sized_opt(size_opt) |push| {
for lhs.each |x| { push(copy *x); }
for rhs.each |x| { push(copy *x); }
}
}
/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline]
pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
do build_sized_opt(v.size_hint()) |push| {
for v.each |x| { push(copy *x); }
}
}

View file

@ -14,7 +14,7 @@
#[lang="drop"]
pub trait Drop {
fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton
fn drop(&self);
}
#[lang="add"]

View file

@ -121,13 +121,13 @@ impl<T> Option<T> {
/// Returns true if the option equals `none`
#[inline]
pub fn is_none(&const self) -> bool {
pub fn is_none(&self) -> bool {
match *self { None => true, Some(_) => false }
}
/// Returns true if the option contains some value
#[inline]
pub fn is_some(&const self) -> bool { !self.is_none() }
pub fn is_some(&self) -> bool { !self.is_none() }
/// Update an optional value by optionally running its content through a
/// function that returns an option.
@ -159,6 +159,15 @@ impl<T> Option<T> {
}
}
/// Filters an optional value using given function.
#[inline(always)]
pub fn filtered<'a>(self, f: &fn(t: &'a T) -> bool) -> Option<T> {
match self {
Some(x) => if(f(&x)) {Some(x)} else {None},
None => None
}
}
/// Maps a `some` value from one type to another by reference
#[inline]
pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> {
@ -407,7 +416,7 @@ fn test_unwrap_resource() {
#[unsafe_destructor]
impl ::ops::Drop for R {
fn finalize(&self) { *(self.i) += 1; }
fn drop(&self) { *(self.i) += 1; }
}
fn R(i: @mut int) -> R {
@ -438,7 +447,7 @@ fn test_option_dance() {
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
let mut y = Some(util::NonCopyable::new());
let mut y = Some(util::NonCopyable);
let _y2 = y.swap_unwrap();
let _y3 = y.swap_unwrap();
}
@ -464,3 +473,11 @@ fn test_get_or_zero() {
let no_stuff: Option<int> = None;
assert_eq!(no_stuff.get_or_zero(), 0);
}
#[test]
fn test_filtered() {
let some_stuff = Some(42);
let modified_stuff = some_stuff.filtered(|&x| {x < 10});
assert_eq!(some_stuff.get(), 42);
assert!(modified_stuff.is_none());
}

View file

@ -29,19 +29,17 @@
#[allow(missing_doc)];
use cast;
use container::Container;
use io;
use iterator::IteratorUtil;
use libc;
use libc::{c_char, c_void, c_int, size_t};
use libc::{mode_t, FILE};
use libc::FILE;
use local_data;
use option;
use option::{Some, None};
use os;
use prelude::*;
use ptr;
use rt;
use rt::TaskContext;
use str;
use uint;
use unstable::finally::Finally;
@ -137,7 +135,7 @@ pub mod win32 {
}
}
if k != 0 && done {
let sub = vec::slice(buf, 0u, k as uint);
let sub = buf.slice(0, k as uint);
res = option::Some(str::from_utf16(sub));
}
}
@ -148,7 +146,7 @@ pub mod win32 {
pub fn as_utf16_p<T>(s: &str, f: &fn(*u16) -> T) -> T {
let mut t = s.to_utf16();
// Null terminate before passing on.
t += [0u16];
t.push(0u16);
vec::as_imm_buf(t, |buf, _len| f(buf))
}
}
@ -183,7 +181,6 @@ pub fn env() -> ~[(~str,~str)] {
unsafe {
#[cfg(windows)]
unsafe fn get_env_pairs() -> ~[~str] {
use libc::types::os::arch::extra::LPTCH;
use libc::funcs::extra::kernel32::{
GetEnvironmentStringsA,
FreeEnvironmentStringsA
@ -226,7 +223,7 @@ pub fn env() -> ~[(~str,~str)] {
fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
let mut pairs = ~[];
for input.each |p| {
for input.iter().advance |p| {
let vs: ~[&str] = p.splitn_iter('=', 1).collect();
debug!("splitting: len: %u",
vs.len());
@ -250,10 +247,10 @@ pub fn getenv(n: &str) -> Option<~str> {
do with_env_lock {
let s = str::as_c_str(n, |s| libc::getenv(s));
if ptr::null::<u8>() == cast::transmute(s) {
option::None::<~str>
None::<~str>
} else {
let s = cast::transmute(s);
option::Some::<~str>(str::raw::from_buf(s))
Some::<~str>(str::raw::from_buf(s))
}
}
}
@ -542,7 +539,7 @@ pub fn homedir() -> Option<Path> {
#[cfg(windows)]
fn secondary() -> Option<Path> {
do getenv(~"USERPROFILE").chain |p| {
do getenv("USERPROFILE").chain |p| {
if !p.is_empty() {
Some(Path(p))
} else {
@ -595,9 +592,10 @@ pub fn tmpdir() -> Path {
/// Recursively walk a directory structure
pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
list_dir(p).each(|q| {
let r = list_dir(p);
r.iter().advance(|q| {
let path = &p.push(*q);
f(path) && (!path_is_dir(path) || walk_dir(path, f))
f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
})
}
@ -648,9 +646,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
use os::win32::as_utf16_p;
// FIXME: turn mode into something useful? #2623
do as_utf16_p(p.to_str()) |buf| {
libc::CreateDirectoryW(buf, unsafe {
cast::transmute(0)
})
libc::CreateDirectoryW(buf, cast::transmute(0))
!= (0 as libc::BOOL)
}
}
@ -660,7 +656,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
fn mkdir(p: &Path, mode: c_int) -> bool {
unsafe {
do as_c_charp(p.to_str()) |c| {
libc::mkdir(c, mode as mode_t) == (0 as c_int)
libc::mkdir(c, mode as libc::mode_t) == (0 as c_int)
}
}
}
@ -733,9 +729,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
}
#[cfg(windows)]
unsafe fn get_list(p: &Path) -> ~[~str] {
use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL};
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
use libc::wcslen;
use libc::{wcslen, free};
use libc::funcs::extra::kernel32::{
FindFirstFileW,
FindNextFileW,
@ -744,7 +739,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
use os::win32::{
as_utf16_p
};
use rt::global_heap::{malloc_raw, free_raw};
use rt::global_heap::malloc_raw;
#[nolink]
extern {
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
@ -759,7 +755,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
FindFirstFileW(
path_ptr,
::cast::transmute(wfd_ptr));
if find_handle as int != INVALID_HANDLE_VALUE {
if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
let mut more_files = 1 as libc::c_int;
while more_files != 0 {
let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
@ -777,7 +773,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
::cast::transmute(wfd_ptr));
}
FindClose(find_handle);
free_raw(wfd_ptr);
free(wfd_ptr)
}
strings
}
@ -962,7 +958,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
// Give the new file the old file's permissions
if do str::as_c_str(to.to_str()) |to_buf| {
libc::chmod(to_buf, from_mode as mode_t)
libc::chmod(to_buf, from_mode as libc::mode_t)
} != 0 {
return false; // should be a condition...
}
@ -1146,7 +1142,7 @@ pub fn set_exit_status(code: int) {
unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
let mut args = ~[];
for uint::range(0, argc as uint) |i| {
vec::push(&mut args, str::raw::from_c_str(*argv.offset(i)));
args.push(str::raw::from_c_str(*argv.offset(i)));
}
args
}
@ -1169,6 +1165,9 @@ pub fn real_args() -> ~[~str] {
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
pub fn real_args() -> ~[~str] {
use rt;
use rt::TaskContext;
if rt::context() == TaskContext {
match rt::args::clone() {
Some(args) => args,
@ -1199,8 +1198,7 @@ pub fn real_args() -> ~[~str] {
while *ptr.offset(len) != 0 { len += 1; }
// Push it onto the list.
vec::push(&mut args,
vec::raw::buf_as_slice(ptr, len,
args.push(vec::raw::buf_as_slice(ptr, len,
str::from_utf16));
}
}
@ -1337,7 +1335,7 @@ pub fn glob(pattern: &str) -> ~[Path] {
/// Returns a vector of Path objects that match the given glob pattern
#[cfg(target_os = "win32")]
pub fn glob(pattern: &str) -> ~[Path] {
pub fn glob(_pattern: &str) -> ~[Path] {
fail!("glob() is unimplemented on Windows")
}
@ -1514,7 +1512,10 @@ mod tests {
fn test_getenv_big() {
let mut s = ~"";
let mut i = 0;
while i < 100 { s += "aaaaaaaaaa"; i += 1; }
while i < 100 {
s = s + "aaaaaaaaaa";
i += 1;
}
let n = make_rand_name();
setenv(n, s);
debug!(copy s);
@ -1537,7 +1538,7 @@ mod tests {
fn test_env_getenv() {
let e = env();
assert!(e.len() > 0u);
for e.each |p| {
for e.iter().advance |p| {
let (n, v) = copy *p;
debug!(copy n);
let v2 = getenv(n);
@ -1554,10 +1555,10 @@ mod tests {
let mut e = env();
setenv(n, "VALUE");
assert!(!vec::contains(e, &(copy n, ~"VALUE")));
assert!(!e.contains(&(copy n, ~"VALUE")));
e = env();
assert!(vec::contains(e, &(n, ~"VALUE")));
assert!(e.contains(&(n, ~"VALUE")));
}
#[test]
@ -1608,8 +1609,8 @@ mod tests {
setenv("USERPROFILE", "/home/PaloAlto");
assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
oldhome.each(|s| { setenv("HOME", *s); true });
olduserprofile.each(|s| { setenv("USERPROFILE", *s); true });
oldhome.iter().advance(|s| { setenv("HOME", *s); true });
olduserprofile.iter().advance(|s| { setenv("USERPROFILE", *s); true });
}
#[test]
@ -1629,7 +1630,7 @@ mod tests {
// Just assuming that we've got some contents in the current directory
assert!(dirs.len() > 0u);
for dirs.each |dir| {
for dirs.iter().advance |dir| {
debug!(copy *dir);
}
}
@ -1725,5 +1726,5 @@ mod tests {
assert!(!os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
}
// More recursive_mkdir tests are in std::tempfile
// More recursive_mkdir tests are in extra::tempfile
}

View file

@ -21,12 +21,11 @@ use cmp::Eq;
use iterator::IteratorUtil;
use libc;
use option::{None, Option, Some};
use str::{OwnedStr, Str, StrSlice, StrVector};
use str;
use str::{Str, StrSlice, StrVector};
use to_str::ToStr;
use ascii::{AsciiCast, AsciiStr};
use old_iter::BaseIter;
use vec::OwnedVector;
use vec::{OwnedVector, ImmutableVector};
#[cfg(windows)]
pub use Path = self::WindowsPath;
@ -128,7 +127,6 @@ pub trait GenericPath {
#[cfg(target_os = "android")]
mod stat {
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "arm")]
pub mod arch {
use libc;
@ -158,6 +156,35 @@ mod stat {
}
}
#[cfg(target_arch = "arm")]
pub mod arch {
use libc;
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
__pad0: [0, ..4],
__st_ino: 0,
st_mode: 0,
st_nlink: 0,
st_uid: 0,
st_gid: 0,
st_rdev: 0,
__pad3: [0, ..4],
st_size: 0,
st_blksize: 0,
st_blocks: 0,
st_atime: 0,
st_atime_nsec: 0,
st_mtime: 0,
st_mtime_nsec: 0,
st_ctime: 0,
st_ctime_nsec: 0,
st_ino: 0
}
}
}
#[cfg(target_arch = "mips")]
pub mod arch {
use libc;
@ -308,8 +335,8 @@ mod stat {
}
}
impl Path {
#[cfg(target_os = "win32")]
impl WindowsPath {
pub fn stat(&self) -> Option<libc::stat> {
unsafe {
do str::as_c_str(self.to_str()) |buf| {
@ -322,19 +349,6 @@ impl Path {
}
}
#[cfg(unix)]
pub fn lstat(&self) -> Option<libc::stat> {
unsafe {
do str::as_c_str(self.to_str()) |buf| {
let mut st = stat::arch::default_stat();
match libc::lstat(buf, &mut st) {
0 => Some(st),
_ => None,
}
}
}
}
pub fn exists(&self) -> bool {
match self.stat() {
None => false,
@ -357,10 +371,55 @@ impl Path {
}
}
#[cfg(not(target_os = "win32"))]
impl PosixPath {
pub fn stat(&self) -> Option<libc::stat> {
unsafe {
do str::as_c_str(self.to_str()) |buf| {
let mut st = stat::arch::default_stat();
match libc::stat(buf, &mut st) {
0 => Some(st),
_ => None,
}
}
}
}
pub fn exists(&self) -> bool {
match self.stat() {
None => false,
Some(_) => true,
}
}
pub fn get_size(&self) -> Option<i64> {
match self.stat() {
None => None,
Some(ref st) => Some(st.st_size as i64),
}
}
pub fn get_mode(&self) -> Option<uint> {
match self.stat() {
None => None,
Some(ref st) => Some(st.st_mode as uint),
}
}
/// Execute a function on p as well as all of its ancestors
pub fn each_parent(&self, f: &fn(&Path)) {
if !self.components.is_empty() {
f(self);
self.pop().each_parent(f);
}
}
}
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
impl Path {
impl PosixPath {
pub fn get_atime(&self) -> Option<(i64, int)> {
match self.stat() {
None => None,
@ -392,9 +451,24 @@ impl Path {
}
}
#[cfg(unix)]
impl PosixPath {
pub fn lstat(&self) -> Option<libc::stat> {
unsafe {
do str::as_c_str(self.to_str()) |buf| {
let mut st = stat::arch::default_stat();
match libc::lstat(buf, &mut st) {
0 => Some(st),
_ => None,
}
}
}
}
}
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
impl Path {
impl PosixPath {
pub fn get_birthtime(&self) -> Option<(i64, int)> {
match self.stat() {
None => None,
@ -407,7 +481,7 @@ impl Path {
}
#[cfg(target_os = "win32")]
impl Path {
impl WindowsPath {
pub fn get_atime(&self) -> Option<(i64, int)> {
match self.stat() {
None => None,
@ -434,13 +508,21 @@ impl Path {
}
}
}
/// Execute a function on p as well as all of its ancestors
pub fn each_parent(&self, f: &fn(&Path)) {
if !self.components.is_empty() {
f(self);
self.pop().each_parent(f);
}
}
}
impl ToStr for PosixPath {
fn to_str(&self) -> ~str {
let mut s = ~"";
if self.is_absolute {
s += "/";
s.push_str("/");
}
s + self.components.connect("/")
}
@ -568,7 +650,7 @@ impl GenericPath for PosixPath {
fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
let mut v = copy self.components;
for cs.each |e| {
for cs.iter().advance |e| {
for e.as_slice().split_iter(windows::is_sep).advance |s| {
if !s.is_empty() {
v.push(s.to_owned())
@ -619,15 +701,21 @@ impl ToStr for WindowsPath {
fn to_str(&self) -> ~str {
let mut s = ~"";
match self.host {
Some(ref h) => { s += "\\\\"; s += *h; }
Some(ref h) => {
s.push_str("\\\\");
s.push_str(*h);
}
None => { }
}
match self.device {
Some(ref d) => { s += *d; s += ":"; }
Some(ref d) => {
s.push_str(*d);
s.push_str(":");
}
None => { }
}
if self.is_absolute {
s += "\\";
s.push_str("\\");
}
s + self.components.connect("\\")
}
@ -825,7 +913,7 @@ impl GenericPath for WindowsPath {
fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
let mut v = copy self.components;
for cs.each |e| {
for cs.iter().advance |e| {
for e.as_slice().split_iter(windows::is_sep).advance |s| {
if !s.is_empty() {
v.push(s.to_owned())
@ -887,7 +975,7 @@ impl GenericPath for WindowsPath {
pub fn normalize(components: &[~str]) -> ~[~str] {
let mut cs = ~[];
for components.each |c| {
for components.iter().advance |c| {
if *c == ~"." && components.len() > 1 { loop; }
if *c == ~"" { loop; }
if *c == ~".." && cs.len() != 0 {

View file

@ -88,7 +88,7 @@ use container::Container;
use cast::{forget, transmute, transmute_copy, transmute_mut};
use either::{Either, Left, Right};
use iterator::IteratorUtil;
use kinds::Owned;
use kinds::Send;
use libc;
use ops::Drop;
use option::{None, Option, Some};
@ -177,7 +177,7 @@ impl PacketHeader {
transmute_copy(&self.buffer)
}
pub fn set_buffer<T:Owned>(&mut self, b: ~Buffer<T>) {
pub fn set_buffer<T:Send>(&mut self, b: ~Buffer<T>) {
unsafe {
self.buffer = transmute_copy(&b);
}
@ -193,13 +193,13 @@ pub trait HasBuffer {
fn set_buffer(&mut self, b: *libc::c_void);
}
impl<T:Owned> HasBuffer for Packet<T> {
impl<T:Send> HasBuffer for Packet<T> {
fn set_buffer(&mut self, b: *libc::c_void) {
self.header.buffer = b;
}
}
pub fn mk_packet<T:Owned>() -> Packet<T> {
pub fn mk_packet<T:Send>() -> Packet<T> {
Packet {
header: PacketHeader(),
payload: None,
@ -230,7 +230,7 @@ pub fn packet<T>() -> *mut Packet<T> {
p
}
pub fn entangle_buffer<T:Owned,Tstart:Owned>(
pub fn entangle_buffer<T:Send,Tstart:Send>(
mut buffer: ~Buffer<T>,
init: &fn(*libc::c_void, x: &mut T) -> *mut Packet<Tstart>)
-> (RecvPacketBuffered<Tstart, T>, SendPacketBuffered<Tstart, T>) {
@ -309,7 +309,7 @@ struct BufferResource<T> {
#[unsafe_destructor]
impl<T> Drop for BufferResource<T> {
fn finalize(&self) {
fn drop(&self) {
unsafe {
// FIXME(#4330) Need self by value to get mutability.
let this: &mut BufferResource<T> = transmute_mut(self);
@ -396,7 +396,7 @@ pub fn send<T,Tbuffer>(mut p: SendPacketBuffered<T,Tbuffer>,
Fails if the sender closes the connection.
*/
pub fn recv<T:Owned,Tbuffer:Owned>(
pub fn recv<T:Send,Tbuffer:Send>(
p: RecvPacketBuffered<T, Tbuffer>) -> T {
try_recv(p).expect("connection closed")
}
@ -407,7 +407,7 @@ Returns `None` if the sender has closed the connection without sending
a message, or `Some(T)` if a message was received.
*/
pub fn try_recv<T:Owned,Tbuffer:Owned>(mut p: RecvPacketBuffered<T, Tbuffer>)
pub fn try_recv<T:Send,Tbuffer:Send>(mut p: RecvPacketBuffered<T, Tbuffer>)
-> Option<T> {
let p_ = p.unwrap();
let p = unsafe { &mut *p_ };
@ -427,7 +427,7 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(mut p: RecvPacketBuffered<T, Tbuffer>)
}
}
fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
fn try_recv_<T:Send>(p: &mut Packet<T>) -> Option<T> {
// optimistic path
match p.header.state {
Full => {
@ -511,7 +511,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
}
/// Returns true if messages are available.
pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
pub fn peek<T:Send,Tb:Send>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
unsafe {
match (*p.header()).state {
Empty | Terminated => false,
@ -521,7 +521,7 @@ pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
}
}
fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
fn sender_terminate<T:Send>(p: *mut Packet<T>) {
let p = unsafe {
&mut *p
};
@ -553,7 +553,7 @@ fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
}
}
fn receiver_terminate<T:Owned>(p: *mut Packet<T>) {
fn receiver_terminate<T:Send>(p: *mut Packet<T>) {
let p = unsafe {
&mut *p
};
@ -671,8 +671,8 @@ pub struct SendPacketBuffered<T, Tbuffer> {
}
#[unsafe_destructor]
impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
fn finalize(&self) {
impl<T:Send,Tbuffer:Send> Drop for SendPacketBuffered<T,Tbuffer> {
fn drop(&self) {
unsafe {
let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
if this.p != None {
@ -729,8 +729,8 @@ pub struct RecvPacketBuffered<T, Tbuffer> {
}
#[unsafe_destructor]
impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
fn finalize(&self) {
impl<T:Send,Tbuffer:Send> Drop for RecvPacketBuffered<T,Tbuffer> {
fn drop(&self) {
unsafe {
let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
if this.p != None {
@ -741,7 +741,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
}
}
impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
impl<T:Send,Tbuffer:Send> RecvPacketBuffered<T, Tbuffer> {
pub fn unwrap(&mut self) -> *mut Packet<T> {
replace(&mut self.p, None).unwrap()
}
@ -751,7 +751,7 @@ impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
}
}
impl<T:Owned,Tbuffer:Owned> Selectable for RecvPacketBuffered<T, Tbuffer> {
impl<T:Send,Tbuffer:Send> Selectable for RecvPacketBuffered<T, Tbuffer> {
fn header(&mut self) -> *mut PacketHeader {
match self.p {
Some(packet) => unsafe {
@ -807,7 +807,7 @@ Sometimes messages will be available on both endpoints at once. In
this case, `select2` may return either `left` or `right`.
*/
pub fn select2<A:Owned,Ab:Owned,B:Owned,Bb:Owned>(
pub fn select2<A:Send,Ab:Send,B:Send,Bb:Send>(
mut a: RecvPacketBuffered<A, Ab>,
mut b: RecvPacketBuffered<B, Bb>)
-> Either<(Option<A>, RecvPacketBuffered<B, Bb>),
@ -847,7 +847,7 @@ pub fn select2i<A:Selectable,B:Selectable>(a: &mut A, b: &mut B)
/// Waits on a set of endpoints. Returns a message, its index, and a
/// list of the remaining endpoints.
pub fn select<T:Owned,Tb:Owned>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
pub fn select<T:Send,Tb:Send>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
-> (uint,
Option<T>,
~[RecvPacketBuffered<T, Tb>]) {

View file

@ -29,7 +29,8 @@ Rust's prelude has three main parts:
// Reexported core operators
pub use either::{Either, Left, Right};
pub use kinds::{Const, Copy, Owned, Sized};
pub use kinds::{Copy, Sized};
pub use kinds::{Freeze, Send};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
@ -46,8 +47,6 @@ pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Great
pub use char::Char;
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use old_iter::{BaseIter, ReverseIter, ExtendedIter, EqIter};
pub use old_iter::CopyableIter;
pub use iter::{Times, FromIter};
pub use iterator::{Iterator, IteratorUtil, OrdIterator};
pub use num::{Num, NumCast};
@ -74,8 +73,8 @@ pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTupl
pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
pub use vec::{VectorVector, CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector};
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};
// Reexported runtime types

View file

@ -232,9 +232,9 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
#[allow(missing_doc)]
pub trait RawPtr<T> {
fn is_null(&const self) -> bool;
fn is_not_null(&const self) -> bool;
unsafe fn to_option(&const self) -> Option<&T>;
fn is_null(&self) -> bool;
fn is_not_null(&self) -> bool;
unsafe fn to_option(&self) -> Option<&T>;
fn offset(&self, count: uint) -> Self;
}
@ -242,11 +242,11 @@ pub trait RawPtr<T> {
impl<T> RawPtr<T> for *T {
/// Returns true if the pointer is equal to the null pointer.
#[inline]
fn is_null(&const self) -> bool { is_null(*self) }
fn is_null(&self) -> bool { is_null(*self) }
/// Returns true if the pointer is not equal to the null pointer.
#[inline]
fn is_not_null(&const self) -> bool { is_not_null(*self) }
fn is_not_null(&self) -> bool { is_not_null(*self) }
///
/// Returns `None` if the pointer is null, or else returns the value wrapped
@ -259,7 +259,7 @@ impl<T> RawPtr<T> for *T {
/// be pointing to invalid memory.
///
#[inline]
unsafe fn to_option(&const self) -> Option<&T> {
unsafe fn to_option(&self) -> Option<&T> {
if self.is_null() { None } else {
Some(cast::transmute(*self))
}
@ -274,11 +274,11 @@ impl<T> RawPtr<T> for *T {
impl<T> RawPtr<T> for *mut T {
/// Returns true if the pointer is equal to the null pointer.
#[inline]
fn is_null(&const self) -> bool { is_null(*self) }
fn is_null(&self) -> bool { is_null(*self) }
/// Returns true if the pointer is not equal to the null pointer.
#[inline]
fn is_not_null(&const self) -> bool { is_not_null(*self) }
fn is_not_null(&self) -> bool { is_not_null(*self) }
///
/// Returns `None` if the pointer is null, or else returns the value wrapped
@ -291,7 +291,7 @@ impl<T> RawPtr<T> for *mut T {
/// be pointing to invalid memory.
///
#[inline]
unsafe fn to_option(&const self) -> Option<&T> {
unsafe fn to_option(&self) -> Option<&T> {
if self.is_null() { None } else {
Some(cast::transmute(*self))
}

View file

@ -42,6 +42,7 @@ fn main () {
use cast;
use cmp;
use container::Container;
use int;
use iterator::IteratorUtil;
use local_data;
@ -544,7 +545,7 @@ impl<R: Rng> RngUtil for R {
fn choose_weighted_option<T:Copy>(&mut self, v: &[Weighted<T>])
-> Option<T> {
let mut total = 0u;
for v.each |item| {
for v.iter().advance |item| {
total += item.weight;
}
if total == 0u {
@ -552,7 +553,7 @@ impl<R: Rng> RngUtil for R {
}
let chosen = self.gen_uint_range(0u, total);
let mut so_far = 0u;
for v.each |item| {
for v.iter().advance |item| {
so_far += item.weight;
if so_far > chosen {
return Some(copy item.item);
@ -567,7 +568,7 @@ impl<R: Rng> RngUtil for R {
*/
fn weighted_vec<T:Copy>(&mut self, v: &[Weighted<T>]) -> ~[T] {
let mut r = ~[];
for v.each |item| {
for v.iter().advance |item| {
for uint::range(0u, item.weight) |_i| {
r.push(copy item.item);
}
@ -589,7 +590,7 @@ impl<R: Rng> RngUtil for R {
// invariant: elements with index >= i have been locked in place.
i -= 1u;
// lock element i in place.
vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
values.swap(i, self.gen_uint_range(0u, i + 1u));
}
}
}
@ -720,7 +721,8 @@ impl IsaacRng {
fn isaac(&mut self) {
self.c += 1;
// abbreviations
let mut (a, b) = (self.a, self.b + self.c);
let mut a = self.a;
let mut b = self.b + self.c;
static midpoint: uint = RAND_SIZE as uint / 2;
@ -746,7 +748,8 @@ impl IsaacRng {
}}
);
for [(0, midpoint), (midpoint, 0)].each |&(mr_offset, m2_offset)| {
let r = [(0, midpoint), (midpoint, 0)];
for r.iter().advance |&(mr_offset, m2_offset)| {
for uint::range_step(0, midpoint, 4) |base| {
rngstep!(0, 13);
rngstep!(1, -6);
@ -843,7 +846,7 @@ fn tls_rng_state(_v: @@mut IsaacRng) {}
* `task_rng().gen::<int>()`.
*/
#[inline]
pub fn task_rng() -> @@mut IsaacRng {
pub fn task_rng() -> @mut IsaacRng {
let r : Option<@@mut IsaacRng>;
unsafe {
r = local_data::local_data_get(tls_rng_state);
@ -853,20 +856,18 @@ pub fn task_rng() -> @@mut IsaacRng {
unsafe {
let rng = @@mut IsaacRng::new_seeded(seed());
local_data::local_data_set(tls_rng_state, rng);
rng
*rng
}
}
Some(rng) => rng
Some(rng) => *rng
}
}
// Allow direct chaining with `task_rng`
impl<R: Rng> Rng for @@mut R {
impl<R: Rng> Rng for @mut R {
#[inline]
fn next(&mut self) -> u32 {
match *self {
@@ref mut r => r.next()
}
(**self).next()
}
}
@ -876,9 +877,7 @@ impl<R: Rng> Rng for @@mut R {
*/
#[inline]
pub fn random<T: Rand>() -> T {
match *task_rng() {
@ref mut r => r.gen()
}
task_rng().gen()
}
#[cfg(test)]

View file

@ -89,7 +89,8 @@ impl Rand for StandardNormal {
// do-while, so the condition should be true on the first
// run, they get overwritten anyway (0 < 1, so these are
// good).
let mut (x, y) = (1.0, 0.0);
let mut x = 1.0;
let mut y = 0.0;
// XXX infinities?
while -2.0*y < x * x {

View file

@ -16,8 +16,10 @@ Runtime type reflection
#[allow(missing_doc)];
use intrinsic::{TyDesc, TyVisitor};
use intrinsic::Opaque;
#[cfg(stage0)]
use intrinsic::{Opaque, TyDesc, TyVisitor};
#[cfg(not(stage0))]
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
use libc::c_void;
use sys;
use vec;

View file

@ -19,9 +19,6 @@ More runtime type reflection
use cast::transmute;
use char;
use container::Container;
use intrinsic;
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
use intrinsic::Opaque;
use io::{Writer, WriterUtil};
use iterator::IteratorUtil;
use libc::c_void;
@ -34,6 +31,10 @@ use to_str::ToStr;
use vec::raw::{VecRepr, SliceRepr};
use vec;
use vec::{OwnedVector, UnboxedVecRepr};
#[cfg(stage0)]
use intrinsic::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
#[cfg(not(stage0))]
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
#[cfg(test)] use io;
@ -56,9 +57,9 @@ impl EscapedCharWriter for @Writer {
'"' => self.write_str("\\\""),
'\x20'..'\x7e' => self.write_char(ch),
_ => {
// FIXME #4423: This is inefficient because it requires a
// malloc.
self.write_str(char::escape_unicode(ch))
do char::escape_unicode(ch) |c| {
self.write_char(c);
}
}
}
}
@ -80,65 +81,35 @@ impl Repr for bool {
}
}
impl Repr for int {
fn write_repr(&self, writer: @Writer) { writer.write_int(*self); }
}
impl Repr for i8 {
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
}
impl Repr for i16 {
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
}
impl Repr for i32 {
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
}
impl Repr for i64 {
// FIXME #4424: This can lose precision.
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
}
impl Repr for uint {
fn write_repr(&self, writer: @Writer) { writer.write_uint(*self); }
}
impl Repr for u8 {
macro_rules! int_repr(($ty:ident) => (impl Repr for $ty {
fn write_repr(&self, writer: @Writer) {
writer.write_uint(*self as uint);
do ::$ty::to_str_bytes(*self, 10u) |bits| {
writer.write(bits);
}
}
}
impl Repr for u16 {
fn write_repr(&self, writer: @Writer) {
writer.write_uint(*self as uint);
}
}
impl Repr for u32 {
fn write_repr(&self, writer: @Writer) {
writer.write_uint(*self as uint);
}
}
impl Repr for u64 {
// FIXME #4424: This can lose precision.
fn write_repr(&self, writer: @Writer) {
writer.write_uint(*self as uint);
}
}
}))
impl Repr for float {
// FIXME #4423: This mallocs.
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
}
impl Repr for f32 {
// FIXME #4423 This mallocs.
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
}
impl Repr for f64 {
// FIXME #4423: This mallocs.
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
}
int_repr!(int)
int_repr!(i8)
int_repr!(i16)
int_repr!(i32)
int_repr!(i64)
int_repr!(uint)
int_repr!(u8)
int_repr!(u16)
int_repr!(u32)
int_repr!(u64)
impl Repr for char {
fn write_repr(&self, writer: @Writer) { writer.write_char(*self); }
}
macro_rules! num_repr(($ty:ident) => (impl Repr for $ty {
fn write_repr(&self, writer: @Writer) {
let s = self.to_str();
writer.write(s.as_bytes());
}
}))
num_repr!(float)
num_repr!(f32)
num_repr!(f64)
// New implementation using reflect::MovePtr
@ -564,6 +535,7 @@ impl TyVisitor for ReprVisitor {
fn visit_self(&self) -> bool { true }
fn visit_type(&self) -> bool { true }
#[cfg(not(stage0))]
fn visit_opaque_box(&self) -> bool {
self.writer.write_char('@');
do self.get::<&managed::raw::BoxRepr> |b| {
@ -571,6 +543,16 @@ impl TyVisitor for ReprVisitor {
self.visit_ptr_inner(p, b.header.type_desc);
}
}
#[cfg(stage0)]
fn visit_opaque_box(&self) -> bool {
self.writer.write_char('@');
do self.get::<&managed::raw::BoxRepr> |b| {
let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
unsafe {
self.visit_ptr_inner(p, transmute(b.header.type_desc));
}
}
}
// Type no longer exists, vestigial function.
fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); }
@ -581,7 +563,7 @@ impl TyVisitor for ReprVisitor {
pub fn write_repr<T>(writer: @Writer, object: &T) {
unsafe {
let ptr = ptr::to_unsafe_ptr(object) as *c_void;
let tydesc = intrinsic::get_tydesc::<T>();
let tydesc = get_tydesc::<T>();
let u = ReprVisitor(ptr, writer);
let v = reflect::MovePtrAdaptor(u);
visit_tydesc(tydesc, @v as @TyVisitor)

View file

@ -16,10 +16,10 @@ use cmp::Eq;
use either;
use either::Either;
use kinds::Copy;
use iterator::IteratorUtil;
use option::{None, Option, Some};
use old_iter::BaseIter;
use vec;
use vec::OwnedVector;
use vec::{OwnedVector, ImmutableVector};
use container::Container;
/// The result type
@ -303,7 +303,7 @@ pub fn map_vec<T,U:Copy,V:Copy>(
ts: &[T], op: &fn(&T) -> Result<V,U>) -> Result<~[V],U> {
let mut vs: ~[V] = vec::with_capacity(ts.len());
for ts.each |t| {
for ts.iter().advance |t| {
match op(t) {
Ok(v) => vs.push(v),
Err(u) => return Err(u)

View file

@ -19,9 +19,9 @@ use option::*;
use cast;
use util;
use ops::Drop;
use kinds::Owned;
use rt::sched::{Scheduler};
use rt::task::Task;
use kinds::Send;
use rt::sched::Scheduler;
use rt::local::Local;
use unstable::atomics::{AtomicUint, AtomicOption, SeqCst};
use unstable::sync::UnsafeAtomicRcBox;
@ -71,7 +71,7 @@ pub struct PortOneHack<T> {
suppress_finalize: bool
}
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
let packet: ~Packet<T> = ~Packet {
state: AtomicUint::new(STATE_BOTH),
payload: None
@ -242,7 +242,7 @@ impl<T> Peekable<T> for PortOne<T> {
#[unsafe_destructor]
impl<T> Drop for ChanOneHack<T> {
fn finalize(&self) {
fn drop(&self) {
if self.suppress_finalize { return }
unsafe {
@ -269,7 +269,7 @@ impl<T> Drop for ChanOneHack<T> {
#[unsafe_destructor]
impl<T> Drop for PortOneHack<T> {
fn finalize(&self) {
fn drop(&self) {
if self.suppress_finalize { return }
unsafe {
@ -330,20 +330,20 @@ pub struct Port<T> {
next: Cell<StreamPortOne<T>>
}
pub fn stream<T: Owned>() -> (Port<T>, Chan<T>) {
pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
let (pone, cone) = oneshot();
let port = Port { next: Cell::new(pone) };
let chan = Chan { next: Cell::new(cone) };
return (port, chan);
}
impl<T: Owned> GenericChan<T> for Chan<T> {
impl<T: Send> GenericChan<T> for Chan<T> {
fn send(&self, val: T) {
self.try_send(val);
}
}
impl<T: Owned> GenericSmartChan<T> for Chan<T> {
impl<T: Send> GenericSmartChan<T> for Chan<T> {
fn try_send(&self, val: T) -> bool {
let (next_pone, next_cone) = oneshot();
let cone = self.next.take();
@ -393,13 +393,13 @@ impl<T> SharedChan<T> {
}
}
impl<T: Owned> GenericChan<T> for SharedChan<T> {
impl<T: Send> GenericChan<T> for SharedChan<T> {
fn send(&self, val: T) {
self.try_send(val);
}
}
impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
fn try_send(&self, val: T) -> bool {
unsafe {
let (next_pone, next_cone) = oneshot();
@ -433,7 +433,7 @@ impl<T> SharedPort<T> {
}
}
impl<T: Owned> GenericPort<T> for SharedPort<T> {
impl<T: Send> GenericPort<T> for SharedPort<T> {
fn recv(&self) -> T {
match self.try_recv() {
Some(val) => val,
@ -475,12 +475,12 @@ impl<T> Clone for SharedPort<T> {
// XXX: Need better name
type MegaPipe<T> = (SharedPort<T>, SharedChan<T>);
pub fn megapipe<T: Owned>() -> MegaPipe<T> {
pub fn megapipe<T: Send>() -> MegaPipe<T> {
let (port, chan) = stream();
(SharedPort::new(port), SharedChan::new(chan))
}
impl<T: Owned> GenericChan<T> for MegaPipe<T> {
impl<T: Send> GenericChan<T> for MegaPipe<T> {
fn send(&self, val: T) {
match *self {
(_, ref c) => c.send(val)
@ -488,7 +488,7 @@ impl<T: Owned> GenericChan<T> for MegaPipe<T> {
}
}
impl<T: Owned> GenericSmartChan<T> for MegaPipe<T> {
impl<T: Send> GenericSmartChan<T> for MegaPipe<T> {
fn try_send(&self, val: T) -> bool {
match *self {
(_, ref c) => c.try_send(val)
@ -496,7 +496,7 @@ impl<T: Owned> GenericSmartChan<T> for MegaPipe<T> {
}
}
impl<T: Owned> GenericPort<T> for MegaPipe<T> {
impl<T: Send> GenericPort<T> for MegaPipe<T> {
fn recv(&self) -> T {
match *self {
(ref p, _) => p.recv()

View file

@ -8,104 +8,129 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use sys::{TypeDesc, size_of};
use libc::{c_void, size_t, uintptr_t};
use c_malloc = libc::malloc;
use c_free = libc::free;
use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
use managed::raw::{BoxHeaderRepr, BoxRepr};
use cast::transmute;
use unstable::intrinsics::{atomic_xadd,atomic_xsub, atomic_load};
use ptr::null;
use intrinsic::TyDesc;
use unstable::intrinsics::TyDesc;
use sys::size_of;
pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
assert!(td.is_not_null());
let total_size = get_box_size(size, (*td).align);
let p = c_malloc(total_size as size_t);
assert!(p.is_not_null());
// FIXME #3475: Converting between our two different tydesc types
let td: *TyDesc = transmute(td);
let box: &mut BoxRepr = transmute(p);
box.header.ref_count = -1; // Exchange values not ref counted
box.header.type_desc = td;
box.header.prev = null();
box.header.next = null();
inc_count();
return transmute(box);
}
/**
Thin wrapper around libc::malloc, none of the box header
stuff in exchange_alloc::malloc
*/
pub unsafe fn malloc_raw(size: uint) -> *c_void {
let p = c_malloc(size as size_t);
if p.is_null() {
fail!("Failure in malloc_raw: result ptr is null");
}
inc_count();
p
}
pub unsafe fn free(ptr: *c_void) {
assert!(ptr.is_not_null());
dec_count();
c_free(ptr);
}
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
pub unsafe fn free_raw(ptr: *c_void) {
assert!(ptr.is_not_null());
dec_count();
c_free(ptr);
}
fn inc_count() {
unsafe {
let exchange_count = &mut *exchange_count_ptr();
atomic_xadd(exchange_count, 1);
}
}
fn dec_count() {
unsafe {
let exchange_count = &mut *exchange_count_ptr();
atomic_xsub(exchange_count, 1);
}
}
pub fn cleanup() {
unsafe {
let count_ptr = exchange_count_ptr();
let allocations = atomic_load(&*count_ptr);
if allocations != 0 {
rtabort!("exchange heap not empty on exit - %i dangling allocations", allocations);
}
}
extern {
#[rust_stack]
fn abort();
}
#[inline]
fn get_box_size(body_size: uint, body_align: uint) -> uint {
let header_size = size_of::<BoxHeaderRepr>();
// FIXME (#2699): This alignment calculation is suspicious. Is it right?
let total_size = align_to(header_size, body_align) + body_size;
return total_size;
total_size
}
// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
// of two.
#[inline]
fn align_to(size: uint, align: uint) -> uint {
assert!(align != 0);
(size + align - 1) & !(align - 1)
}
fn exchange_count_ptr() -> *mut int {
// XXX: Need mutable globals
unsafe { transmute(&rust_exchange_count) }
/// A wrapper around libc::malloc, aborting on out-of-memory
#[inline]
pub unsafe fn malloc_raw(size: uint) -> *c_void {
let p = malloc(size as size_t);
if p.is_null() {
// we need a non-allocating way to print an error here
abort();
}
p
}
extern {
static rust_exchange_count: uintptr_t;
/// A wrapper around libc::realloc, aborting on out-of-memory
#[inline]
pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
let p = realloc(ptr, size as size_t);
if p.is_null() {
// we need a non-allocating way to print an error here
abort();
}
p
}
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[cfg(stage0, not(test))]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char {
exchange_malloc(td, size)
}
#[cfg(stage0)]
#[inline]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
let td = td as *TyDesc;
let size = size as uint;
assert!(td.is_not_null());
let total_size = get_box_size(size, (*td).align);
let p = malloc_raw(total_size as uint);
let box: *mut BoxRepr = p as *mut BoxRepr;
(*box).header.ref_count = -1;
(*box).header.type_desc = td;
box as *c_char
}
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[cfg(not(stage0), not(test))]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc_(align: u32, size: uintptr_t) -> *c_char {
exchange_malloc(align, size)
}
#[cfg(not(stage0))]
#[inline]
pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char {
let total_size = get_box_size(size as uint, align as uint);
malloc_raw(total_size as uint) as *c_char
}
// FIXME: #7496
#[cfg(not(test))]
#[lang="closure_exchange_malloc"]
#[inline]
pub unsafe fn closure_exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char {
closure_exchange_malloc(td, size)
}
#[inline]
pub unsafe fn closure_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
let td = td as *TyDesc;
let size = size as uint;
assert!(td.is_not_null());
let total_size = get_box_size(size, (*td).align);
let p = malloc_raw(total_size as uint);
let box: *mut BoxRepr = p as *mut BoxRepr;
(*box).header.type_desc = td;
box as *c_char
}
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler.
#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
pub unsafe fn exchange_free_(ptr: *c_char) {
exchange_free(ptr)
}
#[inline]
pub unsafe fn exchange_free(ptr: *c_char) {
free(ptr as *c_void);
}

View file

@ -292,13 +292,13 @@ impl<T: Reader> ReaderUtil for T {
let start_len = buf.len();
let mut total_read = 0;
vec::reserve_at_least(buf, start_len + len);
buf.reserve_at_least(start_len + len);
vec::raw::set_len(buf, start_len + len);
do (|| {
while total_read < len {
let len = buf.len();
let slice = vec::mut_slice(*buf, start_len + total_read, len);
let slice = buf.mut_slice(start_len + total_read, len);
match self.read(slice) {
Some(nread) => {
total_read += nread;
@ -343,7 +343,9 @@ impl<T: Reader> ReaderByteConversions for T {
fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);
let mut (val, pos, i) = (0u64, 0, nbytes);
let mut val = 0u64;
let mut pos = 0;
let mut i = nbytes;
while i > 0 {
val += (self.read_u8() as u64) << pos;
pos += 8;
@ -359,7 +361,8 @@ impl<T: Reader> ReaderByteConversions for T {
fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);
let mut (val, i) = (0u64, nbytes);
let mut val = 0u64;
let mut i = nbytes;
while i > 0 {
i -= 1;
val += (self.read_u8() as u64) << i * 8;

View file

@ -86,7 +86,7 @@ impl Reader for MemReader {
let write_len = min(buf.len(), self.buf.len() - self.pos);
{
let input = self.buf.slice(self.pos, self.pos + write_len);
let output = vec::mut_slice(buf, 0, write_len);
let output = buf.mut_slice(0, write_len);
assert_eq!(input.len(), output.len());
vec::bytes::copy_memory(output, input, write_len);
}

View file

@ -321,7 +321,7 @@ impl JoinLatch {
}
impl Drop for JoinLatch {
fn finalize(&self) {
fn drop(&self) {
rtdebug!("DESTROYING %x", self.id());
rtassert!(self.closed);
}
@ -333,7 +333,6 @@ mod test {
use cell::Cell;
use container::Container;
use iter::Times;
use old_iter::BaseIter;
use rt::test::*;
use rand;
use rand::RngUtil;
@ -552,7 +551,7 @@ mod test {
rtdebug!("depth: %u", depth);
let mut remaining_orders = remaining_orders;
let mut num = 0;
for my_orders.each |&order| {
for my_orders.iter().advance |&order| {
let child_latch = latch.new_child();
let child_latch = Cell::new(child_latch);
let (child_orders, remaining) = split_orders(remaining_orders);
@ -592,7 +591,7 @@ mod test {
orders: ~[Order]
}
fn next(latch: &mut JoinLatch, orders: ~[Order]) {
for orders.each |order| {
for orders.iter().advance |order| {
let suborders = copy order.orders;
let child_latch = Cell::new(latch.new_child());
let succeed = order.succeed;

View file

@ -76,7 +76,7 @@ impl LocalHeap {
}
impl Drop for LocalHeap {
fn finalize(&self) {
fn drop(&self) {
unsafe {
rust_delete_boxed_region(self.boxed_region);
rust_delete_memory_region(self.memory_region);

View file

@ -12,7 +12,7 @@
//! single consumer.
use container::Container;
use kinds::Owned;
use kinds::Send;
use vec::OwnedVector;
use cell::Cell;
use option::*;
@ -24,7 +24,7 @@ pub struct MessageQueue<T> {
priv queue: ~Exclusive<~[T]>
}
impl<T: Owned> MessageQueue<T> {
impl<T: Send> MessageQueue<T> {
pub fn new() -> MessageQueue<T> {
MessageQueue {
queue: ~exclusive(~[])

View file

@ -209,7 +209,6 @@ pub fn init(argc: int, argv: **u8, crate_map: *u8) {
/// One-time runtime cleanup.
pub fn cleanup() {
args::cleanup();
global_heap::cleanup();
}
/// Execute the main function in a scheduler.

View file

@ -74,7 +74,7 @@ impl<T> RC<T> {
#[unsafe_destructor]
impl<T> Drop for RC<T> {
fn finalize(&self) {
fn drop(&self) {
assert!(self.refcount() > 0);
unsafe {

View file

@ -1074,7 +1074,8 @@ mod test {
let n_tasks = 10;
let token = 2000;
let mut (p, ch1) = stream();
let (p, ch1) = stream();
let mut p = p;
ch1.send((token, end_chan));
let mut i = 2;
while i <= n_tasks {
@ -1127,7 +1128,7 @@ mod test {
struct S { field: () }
impl Drop for S {
fn finalize(&self) {
fn drop(&self) {
let _foo = @0;
}
}

View file

@ -49,7 +49,7 @@ impl StackSegment {
}
impl Drop for StackSegment {
fn finalize(&self) {
fn drop(&self) {
unsafe {
// XXX: Using the FFI to call a C macro. Slow
rust_valgrind_stack_deregister(self.valgrind_id);

View file

@ -219,7 +219,7 @@ impl Task {
}
impl Drop for Task {
fn finalize(&self) { assert!(self.destroyed) }
fn drop(&self) { assert!(self.destroyed) }
}
// Coroutines represent nothing more than a context and a stack

View file

@ -33,7 +33,7 @@ impl Thread {
}
impl Drop for Thread {
fn finalize(&self) {
fn drop(&self) {
unsafe { rust_raw_thread_join_delete(self.raw_thread) }
}
}

View file

@ -60,13 +60,13 @@ pub type Key = DWORD;
#[cfg(windows)]
pub unsafe fn create(key: &mut Key) {
static TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
*key = unsafe { TlsAlloc() };
*key = TlsAlloc();
assert!(*key != TLS_OUT_OF_INDEXES);
}
#[cfg(windows)]
pub unsafe fn set(key: Key, value: *mut c_void) {
unsafe { assert!(0 != TlsSetValue(key, value)) }
assert!(0 != TlsSetValue(key, value))
}
#[cfg(windows)]

View file

@ -389,7 +389,8 @@ mod test {
if status.is_none() {
rtdebug!("got %d bytes", nread);
let buf = buf.unwrap();
for buf.slice(0, nread as uint).each |byte| {
let r = buf.slice(0, nread as uint);
for r.iter().advance |byte| {
assert!(*byte == count as u8);
rtdebug!("%u", *byte as uint);
count += 1;

View file

@ -47,7 +47,7 @@ impl UvEventLoop {
}
impl Drop for UvEventLoop {
fn finalize(&self) {
fn drop(&self) {
// XXX: Need mutable finalizer
let this = unsafe {
transmute::<&UvEventLoop, &mut UvEventLoop>(self)
@ -139,7 +139,7 @@ impl RemoteCallback for UvRemoteCallback {
}
impl Drop for UvRemoteCallback {
fn finalize(&self) {
fn drop(&self) {
unsafe {
let this: &mut UvRemoteCallback = cast::transmute_mut(self);
do this.exit_flag.with |should_exit| {
@ -285,7 +285,7 @@ impl UvTcpListener {
}
impl Drop for UvTcpListener {
fn finalize(&self) {
fn drop(&self) {
let watcher = self.watcher();
let scheduler = Local::take::<Scheduler>();
do scheduler.deschedule_running_task_and_then |_, task| {
@ -346,7 +346,7 @@ impl UvTcpStream {
}
impl Drop for UvTcpStream {
fn finalize(&self) {
fn drop(&self) {
rtdebug!("closing tcp stream");
let watcher = self.watcher();
let scheduler = Local::take::<Scheduler>();

View file

@ -15,7 +15,6 @@ use super::io::net::ip::IpAddr;
use super::uv::*;
use super::rtio::*;
use ops::Drop;
use old_iter::CopyableIter;
use cell::Cell;
use cast::transmute;
use super::sched::{Scheduler, local_sched};
@ -43,7 +42,7 @@ impl UvEventLoop {
}
impl Drop for UvEventLoop {
fn finalize(&self) {
fn drop(&self) {
// XXX: Need mutable finalizer
let this = unsafe {
transmute::<&UvEventLoop, &mut UvEventLoop>(self)
@ -165,7 +164,7 @@ impl UvTcpListener {
}
impl Drop for UvTcpListener {
fn finalize(&self) {
fn drop(&self) {
// XXX: Again, this never gets called. Use .close() instead
//self.watcher().as_stream().close(||());
}
@ -231,7 +230,7 @@ impl UvStream {
}
impl Drop for UvStream {
fn finalize(&self) {
fn drop(&self) {
rtdebug!("closing stream");
//self.watcher().close(||());
}

View file

@ -13,7 +13,7 @@ use option::*;
use vec::OwnedVector;
use unstable::sync::{Exclusive, exclusive};
use cell::Cell;
use kinds::Owned;
use kinds::Send;
use clone::Clone;
pub struct WorkQueue<T> {
@ -21,7 +21,7 @@ pub struct WorkQueue<T> {
priv queue: ~Exclusive<~[T]>
}
impl<T: Owned> WorkQueue<T> {
impl<T: Send> WorkQueue<T> {
pub fn new() -> WorkQueue<T> {
WorkQueue {
queue: ~exclusive(~[])

View file

@ -12,11 +12,10 @@
#[allow(missing_doc)];
use iterator::IteratorUtil;
use cast;
use comm::{stream, SharedChan, GenericChan, GenericPort};
use int;
use io;
use iterator::IteratorUtil;
use libc::{pid_t, c_void, c_int};
use libc;
use option::{Some, None};
@ -428,7 +427,7 @@ impl Process {
}
impl Drop for Process {
fn finalize(&self) {
fn drop(&self) {
// FIXME(#4330) Need self by value to get mutability.
let mut_self: &mut Process = unsafe { cast::transmute(self) };
@ -465,7 +464,6 @@ fn spawn_process_os(prog: &str, args: &[~str],
use libc::funcs::extra::msvcrt::get_osfhandle;
use sys;
use uint;
unsafe {
@ -582,7 +580,7 @@ pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
let mut cmd = ~"";
append_arg(&mut cmd, prog);
for args.each |arg| {
for args.iter().advance |arg| {
cmd.push_char(' ');
append_arg(&mut cmd, *arg);
}
@ -638,6 +636,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
use libc::funcs::bsd44::getdtablesize;
use int;
mod rustrt {
use libc::c_void;
@ -698,7 +697,7 @@ fn with_argv<T>(prog: &str, args: &[~str],
cb: &fn(**libc::c_char) -> T) -> T {
let mut argptrs = ~[str::as_c_str(prog, |b| b)];
let mut tmps = ~[];
for args.each |arg| {
for args.iter().advance |arg| {
let t = @copy *arg;
tmps.push(t);
argptrs.push(str::as_c_str(*t, |b| b));
@ -716,7 +715,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
let mut tmps = ~[];
let mut ptrs = ~[];
for es.each |&(k, v)| {
for es.iter().advance |&(k, v)| {
let kv = @fmt!("%s=%s", k, v);
tmps.push(kv);
ptrs.push(str::as_c_str(*kv, |b| b));
@ -739,7 +738,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
match env {
Some(es) => {
let mut blk = ~[];
for es.each |&(k, v)| {
for es.iter().advance |&(k, v)| {
let kv = fmt!("%s=%s", k, v);
blk.push_all(kv.as_bytes_with_null_consume());
}
@ -944,12 +943,20 @@ mod tests {
}
#[test]
#[cfg(not(target_os="android"))]
fn test_process_status() {
assert_eq!(run::process_status("false", []), 1);
assert_eq!(run::process_status("true", []), 0);
}
#[test]
#[cfg(target_os="android")]
fn test_process_status() {
assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"false"]), 1);
assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"true"]), 0);
}
#[test]
#[cfg(not(target_os="android"))]
fn test_process_output_output() {
let run::ProcessOutput {status, output, error}
@ -963,8 +970,24 @@ mod tests {
assert_eq!(error, ~[]);
}
}
#[test]
#[cfg(target_os="android")]
fn test_process_output_output() {
let run::ProcessOutput {status, output, error}
= run::process_output("/system/bin/sh", [~"-c",~"echo hello"]);
let output_str = str::from_bytes(output);
assert_eq!(status, 0);
assert_eq!(output_str.trim().to_owned(), ~"hello");
// FIXME #7224
if !running_on_valgrind() {
assert_eq!(error, ~[]);
}
}
#[test]
#[cfg(not(target_os="android"))]
fn test_process_output_error() {
let run::ProcessOutput {status, output, error}
@ -974,6 +997,17 @@ mod tests {
assert_eq!(output, ~[]);
assert!(!error.is_empty());
}
#[test]
#[cfg(target_os="android")]
fn test_process_output_error() {
let run::ProcessOutput {status, output, error}
= run::process_output("/system/bin/mkdir", [~"."]);
assert_eq!(status, 255);
assert_eq!(output, ~[]);
assert!(!error.is_empty());
}
#[test]
fn test_pipes() {
@ -1024,19 +1058,37 @@ mod tests {
}
#[test]
#[cfg(not(target_os="android"))]
fn test_finish_once() {
let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
assert_eq!(prog.finish(), 1);
}
#[test]
#[cfg(target_os="android")]
fn test_finish_once() {
let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
run::ProcessOptions::new());
assert_eq!(prog.finish(), 1);
}
#[test]
#[cfg(not(target_os="android"))]
fn test_finish_twice() {
let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
assert_eq!(prog.finish(), 1);
assert_eq!(prog.finish(), 1);
}
#[test]
#[cfg(target_os="android")]
fn test_finish_twice() {
let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
run::ProcessOptions::new());
assert_eq!(prog.finish(), 1);
assert_eq!(prog.finish(), 1);
}
#[test]
#[cfg(not(target_os="android"))]
fn test_finish_with_output_once() {
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
@ -1051,8 +1103,26 @@ mod tests {
assert_eq!(error, ~[]);
}
}
#[test]
#[cfg(target_os="android")]
fn test_finish_with_output_once() {
let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
run::ProcessOptions::new());
let run::ProcessOutput {status, output, error}
= prog.finish_with_output();
let output_str = str::from_bytes(output);
assert_eq!(status, 0);
assert_eq!(output_str.trim().to_owned(), ~"hello");
// FIXME #7224
if !running_on_valgrind() {
assert_eq!(error, ~[]);
}
}
#[test]
#[cfg(not(target_os="android"))]
fn test_finish_with_output_twice() {
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
@ -1078,10 +1148,38 @@ mod tests {
assert_eq!(error, ~[]);
}
}
#[test]
#[cfg(target_os="android")]
fn test_finish_with_output_twice() {
let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
run::ProcessOptions::new());
let run::ProcessOutput {status, output, error}
= prog.finish_with_output();
let output_str = str::from_bytes(output);
assert_eq!(status, 0);
assert_eq!(output_str.trim().to_owned(), ~"hello");
// FIXME #7224
if !running_on_valgrind() {
assert_eq!(error, ~[]);
}
let run::ProcessOutput {status, output, error}
= prog.finish_with_output();
assert_eq!(status, 0);
assert_eq!(output, ~[]);
// FIXME #7224
if !running_on_valgrind() {
assert_eq!(error, ~[]);
}
}
#[test]
#[should_fail]
#[cfg(not(windows))]
#[cfg(not(windows),not(target_os="android"))]
fn test_finish_with_output_redirected() {
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions {
env: None,
@ -1093,14 +1191,36 @@ mod tests {
// this should fail because it is not valid to read the output when it was redirected
prog.finish_with_output();
}
#[test]
#[should_fail]
#[cfg(not(windows),target_os="android")]
fn test_finish_with_output_redirected() {
let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
run::ProcessOptions {
env: None,
dir: None,
in_fd: Some(0),
out_fd: Some(1),
err_fd: Some(2)
});
// this should fail because it is not valid to read the output when it was redirected
prog.finish_with_output();
}
#[cfg(unix)]
#[cfg(unix,not(target_os="android"))]
fn run_pwd(dir: Option<&Path>) -> run::Process {
run::Process::new("pwd", [], run::ProcessOptions {
dir: dir,
.. run::ProcessOptions::new()
})
}
#[cfg(unix,target_os="android")]
fn run_pwd(dir: Option<&Path>) -> run::Process {
run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions {
dir: dir,
.. run::ProcessOptions::new()
})
}
#[cfg(windows)]
fn run_pwd(dir: Option<&Path>) -> run::Process {
@ -1142,13 +1262,20 @@ mod tests {
assert_eq!(parent_stat.st_ino, child_stat.st_ino);
}
#[cfg(unix)]
#[cfg(unix,not(target_os="android"))]
fn run_env(env: Option<&[(~str, ~str)]>) -> run::Process {
run::Process::new("env", [], run::ProcessOptions {
env: env,
.. run::ProcessOptions::new()
})
}
#[cfg(unix,target_os="android")]
fn run_env(env: Option<&[(~str, ~str)]>) -> run::Process {
run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions {
env: env,
.. run::ProcessOptions::new()
})
}
#[cfg(windows)]
fn run_env(env: Option<&[(~str, ~str)]>) -> run::Process {
@ -1159,17 +1286,36 @@ mod tests {
}
#[test]
#[cfg(not(target_os="android"))]
fn test_inherit_env() {
if running_on_valgrind() { return; }
let mut prog = run_env(None);
let output = str::from_bytes(prog.finish_with_output().output);
for os::env().each |&(k, v)| {
let r = os::env();
for r.iter().advance |&(k, v)| {
// don't check windows magical empty-named variables
assert!(k.is_empty() || output.contains(fmt!("%s=%s", k, v)));
}
}
#[test]
#[cfg(target_os="android")]
fn test_inherit_env() {
if running_on_valgrind() { return; }
let mut prog = run_env(None);
let output = str::from_bytes(prog.finish_with_output().output);
let r = os::env();
for r.iter().advance |&(k, v)| {
// don't check android RANDOM variables
if k != ~"RANDOM" {
assert!(output.contains(fmt!("%s=%s", k, v)) ||
output.contains(fmt!("%s=\'%s\'", k, v)));
}
}
}
#[test]
fn test_add_to_env() {

View file

@ -49,7 +49,7 @@ they contained the following prologue:
#[link(name = "std",
vers = "0.7-pre",
vers = "0.7",
uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8",
url = "https://github.com/mozilla/rust/tree/master/src/libstd")];
@ -138,7 +138,6 @@ pub mod from_str;
#[path = "num/num.rs"]
pub mod num;
pub mod iter;
pub mod old_iter;
pub mod iterator;
pub mod to_str;
pub mod to_bytes;

View file

@ -14,7 +14,7 @@
* Strings are a packed UTF-8 representation of text, stored as null
* terminated buffers of u8 bytes. Strings should be indexed in bytes,
* for efficiency, but UTF-8 unsafe operations should be avoided. For
* some heavy-duty uses, try std::rope.
* some heavy-duty uses, try extra::rope.
*/
use at_vec;
@ -29,7 +29,6 @@ use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator, MapIter
use libc;
use num::Zero;
use option::{None, Option, Some};
use old_iter::{BaseIter, EqIter};
use ptr;
use ptr::RawPtr;
use to_str::ToStr;
@ -55,12 +54,11 @@ Section: Creating a string
*
* Raises the `not_utf8` condition if invalid UTF-8
*/
pub fn from_bytes(vv: &[u8]) -> ~str {
use str::not_utf8::cond;
if !is_utf8(vv) {
let first_bad_byte = vec::find(vv, |b| !is_utf8([*b])).get();
let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).get();
cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
first_bad_byte as uint))
}
@ -69,6 +67,25 @@ pub fn from_bytes(vv: &[u8]) -> ~str {
}
}
/**
* Consumes a vector of bytes to create a new utf-8 string
*
* # Failure
*
* Raises the `not_utf8` condition if invalid UTF-8
*/
pub fn from_bytes_owned(vv: ~[u8]) -> ~str {
use str::not_utf8::cond;
if !is_utf8(vv) {
let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).get();
cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
first_bad_byte as uint))
} else {
return unsafe { raw::from_bytes_owned(vv) }
}
}
/**
* Convert a vector of bytes to a UTF-8 string.
* The vector needs to be one byte longer than the string, and end with a 0 byte.
@ -147,7 +164,7 @@ pub fn from_char(ch: char) -> ~str {
pub fn from_chars(chs: &[char]) -> ~str {
let mut buf = ~"";
buf.reserve(chs.len());
for chs.each |ch| {
for chs.iter().advance |ch| {
buf.push_char(*ch)
}
buf
@ -358,7 +375,8 @@ impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> {
fn next(&mut self) -> Option<(uint, uint)> {
// See Issue #1932 for why this is a naive search
let (h_len, n_len) = (self.haystack.len(), self.needle.len());
let mut (match_start, match_i) = (0, 0);
let mut match_start = 0;
let mut match_i = 0;
while self.position < h_len {
if self.haystack[self.position] == self.needle[match_i] {
@ -434,10 +452,17 @@ pub fn each_split_within<'a>(ss: &'a str,
let mut last_start = 0;
let mut last_end = 0;
let mut state = A;
let mut fake_i = ss.len();
let mut lim = lim;
let mut cont = true;
let slice: &fn() = || { cont = it(ss.slice(slice_start, last_end)) };
// if the limit is larger than the string, lower it to save cycles
if (lim >= fake_i) {
lim = fake_i;
}
let machine: &fn((uint, char)) -> bool = |(i, c)| {
let whitespace = if char::is_whitespace(c) { Ws } else { Cr };
let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim };
@ -463,10 +488,9 @@ pub fn each_split_within<'a>(ss: &'a str,
cont
};
ss.iter().enumerate().advance(machine);
ss.iter().enumerate().advance(|x| machine(x));
// Let the automaton 'run out' by supplying trailing whitespace
let mut fake_i = ss.len();
while cont && match state { B | C => true, A => false } {
machine((fake_i, ' '));
fake_i += 1;
@ -474,6 +498,31 @@ pub fn each_split_within<'a>(ss: &'a str,
return cont;
}
/**
* Replace all occurrences of one string with another
*
* # Arguments
*
* * s - The string containing substrings to replace
* * from - The string to replace
* * to - The replacement string
*
* # Return value
*
* The original string with all occurances of `from` replaced with `to`
*/
pub fn replace(s: &str, from: &str, to: &str) -> ~str {
let mut result = ~"";
let mut last_end = 0;
for s.matches_index_iter(from).advance |(start, end)| {
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
result.push_str(to);
last_end = end;
}
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
result
}
/*
Section: Comparing strings
*/
@ -544,7 +593,7 @@ Section: Misc
*/
/// Determines if a vector of bytes contains valid UTF-8
pub fn is_utf8(v: &const [u8]) -> bool {
pub fn is_utf8(v: &[u8]) -> bool {
let mut i = 0u;
let total = v.len();
while i < total {
@ -632,6 +681,48 @@ pub fn with_capacity(capacity: uint) -> ~str {
buf
}
/**
* As char_len but for a slice of a string
*
* # Arguments
*
* * s - A valid string
* * start - The position inside `s` where to start counting in bytes
* * end - The position where to stop counting
*
* # Return value
*
* The number of Unicode characters in `s` between the given indices.
*/
pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
assert!(s.is_char_boundary(start));
assert!(s.is_char_boundary(end));
let mut i = start;
let mut len = 0u;
while i < end {
let next = s.char_range_at(i).next;
len += 1u;
i = next;
}
return len;
}
/// Counts the number of bytes taken by the first `n` chars in `s`
/// starting from `start`.
pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
assert!(s.is_char_boundary(start));
let mut end = start;
let mut cnt = n;
let l = s.len();
while cnt > 0u {
assert!(end < l);
let next = s.char_range_at(end).next;
cnt -= 1u;
end = next;
}
end - start
}
/// Given a first byte, determine how many bytes are in this UTF-8 character
pub fn utf8_char_width(b: u8) -> uint {
let byte: uint = b as uint;
@ -694,7 +785,7 @@ impl<'self> StrUtil for &'self str {
// NB: len includes the trailing null.
assert!(len > 0);
if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
to_owned(self).as_c_str(f)
to_owned(self).as_c_str(|s| f(s))
} else {
f(buf as *libc::c_char)
}
@ -738,7 +829,8 @@ pub mod raw {
/// Create a Rust string from a null-terminated *u8 buffer
pub unsafe fn from_buf(buf: *u8) -> ~str {
let mut (curr, i) = (buf, 0u);
let mut curr = buf;
let mut i = 0u;
while *curr != 0u8 {
i += 1u;
curr = ptr::offset(buf, i);
@ -747,7 +839,7 @@ pub mod raw {
}
/// Create a Rust string from a *u8 buffer of the given length
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> ~str {
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
let mut v: ~[u8] = vec::with_capacity(len + 1);
vec::as_mut_buf(v, |vbuf, _len| {
ptr::copy_memory(vbuf, buf as *u8, len)
@ -770,12 +862,19 @@ pub mod raw {
}
/// Converts a vector of bytes to a new owned string.
pub unsafe fn from_bytes(v: &const [u8]) -> ~str {
do vec::as_const_buf(v) |buf, len| {
pub unsafe fn from_bytes(v: &[u8]) -> ~str {
do vec::as_imm_buf(v) |buf, len| {
from_buf_len(buf, len)
}
}
/// Converts an owned vector of bytes to a new owned string. This assumes
/// that the utf-8-ness of the vector has already been validated
pub unsafe fn from_bytes_owned(mut v: ~[u8]) -> ~str {
v.push(0u8);
cast::transmute(v)
}
/// Converts a vector of bytes to a string.
/// The byte slice needs to contain valid utf8 and needs to be one byte longer than
/// the string, if possible ending in a 0 byte.
@ -791,7 +890,8 @@ pub mod raw {
/// invalidated later.
pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
let s = s as *u8;
let mut (curr, len) = (s, 0u);
let mut curr = s;
let mut len = 0u;
while *curr != 0u8 {
len += 1u;
curr = ptr::offset(s, len);
@ -864,7 +964,7 @@ pub mod raw {
unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
let new_len = s.len() + bytes.len();
s.reserve_at_least(new_len);
for bytes.each |byte| { push_byte(&mut *s, *byte); }
for bytes.iter().advance |byte| { push_byte(&mut *s, *byte); }
}
/// Removes the last byte from a string and returns it. (Not UTF-8 safe).
@ -1071,6 +1171,17 @@ impl<'self> Str for @str {
}
}
impl<'self> Container for &'self str {
#[inline]
fn len(&self) -> uint {
do as_buf(*self) |_p, n| { n - 1u }
}
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[allow(missing_doc)]
pub trait StrSlice<'self> {
fn contains<'a>(&self, needle: &'a str) -> bool;
@ -1089,10 +1200,8 @@ pub trait StrSlice<'self> {
fn any_line_iter(&self) -> AnyLineIterator<'self>;
fn word_iter(&self) -> WordIterator<'self>;
fn ends_with(&self, needle: &str) -> bool;
fn is_empty(&self) -> bool;
fn is_whitespace(&self) -> bool;
fn is_alphanumeric(&self) -> bool;
fn len(&self) -> uint;
fn char_len(&self) -> uint;
fn slice(&self, begin: uint, end: uint) -> &'self str;
@ -1293,9 +1402,6 @@ impl<'self> StrSlice<'self> for &'self str {
self.split_iter(char::is_whitespace).filter(|s| !s.is_empty())
}
/// Returns true if the string has length 0
#[inline]
fn is_empty(&self) -> bool { self.len() == 0 }
/**
* Returns true if the string contains only whitespace
*
@ -1310,14 +1416,9 @@ impl<'self> StrSlice<'self> for &'self str {
*/
#[inline]
fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) }
/// Returns the size in bytes not counting the null terminator
#[inline]
fn len(&self) -> uint {
do as_buf(*self) |_p, n| { n - 1u }
}
/// Returns the number of characters that a string holds
#[inline]
fn char_len(&self) -> uint { self.iter().count() }
fn char_len(&self) -> uint { self.iter().len_() }
/**
* Returns a slice of the given string from the byte range
@ -1358,7 +1459,8 @@ impl<'self> StrSlice<'self> for &'self str {
fn slice_chars(&self, begin: uint, end: uint) -> &'self str {
assert!(begin <= end);
// not sure how to use the iterators for this nicely.
let mut (position, count) = (0, 0);
let mut position = 0;
let mut count = 0;
let l = self.len();
while count < begin && position < l {
position = self.char_range_at(position).next;
@ -1395,7 +1497,9 @@ impl<'self> StrSlice<'self> for &'self str {
let mut out: ~str = ~"";
out.reserve_at_least(self.len());
for self.iter().advance |c| {
out.push_str(char::escape_default(c));
do c.escape_default |c| {
out.push_char(c);
}
}
out
}
@ -1405,7 +1509,9 @@ impl<'self> StrSlice<'self> for &'self str {
let mut out: ~str = ~"";
out.reserve_at_least(self.len());
for self.iter().advance |c| {
out.push_str(char::escape_unicode(c));
do c.escape_unicode |c| {
out.push_char(c);
}
}
out
}
@ -1506,7 +1612,8 @@ impl<'self> StrSlice<'self> for &'self str {
* The original string with all occurances of `from` replaced with `to`
*/
pub fn replace(&self, from: &str, to: &str) -> ~str {
let mut (result, last_end) = (~"", 0);
let mut result = ~"";
let mut last_end = 0;
for self.matches_index_iter(from).advance |(start, end)| {
result.push_str(unsafe{raw::slice_bytes(*self, last_end, start)});
result.push_str(to);
@ -2082,7 +2189,7 @@ impl OwnedStr for ~str {
pub fn reserve(&mut self, n: uint) {
unsafe {
let v: *mut ~[u8] = cast::transmute(self);
vec::reserve(&mut *v, n + 1);
(*v).reserve(n + 1);
}
}
@ -2116,8 +2223,8 @@ impl OwnedStr for ~str {
* reallocating
*/
fn capacity(&self) -> uint {
let buf: &const ~[u8] = unsafe { cast::transmute(self) };
let vcap = vec::capacity(buf);
let buf: &~[u8] = unsafe { cast::transmute(self) };
let vcap = buf.capacity();
assert!(vcap > 0u);
vcap - 1u
}
@ -2225,9 +2332,9 @@ mod tests {
use option::Some;
use libc::c_char;
use libc;
use old_iter::BaseIter;
use ptr;
use str::*;
use uint;
use vec;
use vec::{ImmutableVector, CopyableVector};
use cmp::{TotalOrd, Less, Equal, Greater};
@ -2251,7 +2358,7 @@ mod tests {
assert!("" <= "");
assert!("" <= "foo");
assert!("foo" <= "foo");
assert!("foo" != ~"bar");
assert!("foo" != "bar");
}
#[test]
@ -2373,6 +2480,8 @@ mod tests {
t("hello", 15, [~"hello"]);
t("\nMary had a little lamb\nLittle lamb\n", 15,
[~"Mary had a", ~"little lamb", ~"Little lamb"]);
t("\nMary had a little lamb\nLittle lamb\n", uint::max_value,
[~"Mary had a little lamb\nLittle lamb"]);
}
#[test]
@ -3080,7 +3189,7 @@ mod tests {
0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
0x000a_u16 ]) ];
for pairs.each |p| {
for pairs.iter().advance |p| {
let (s, u) = copy *p;
assert!(s.to_utf16() == u);
assert!(from_utf16(u) == s);
@ -3094,7 +3203,7 @@ mod tests {
let s = ~"ศไทย中华Việt Nam";
let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
let mut pos = 0;
for v.each |ch| {
for v.iter().advance |ch| {
assert!(s.char_at(pos) == *ch);
pos += from_char(*ch).len();
}
@ -3158,6 +3267,7 @@ mod tests {
#[test]
fn test_add() {
#[allow(unnecessary_allocation)];
macro_rules! t (
($s1:expr, $s2:expr, $e:expr) => {
assert_eq!($s1 + $s2, $e);

View file

@ -14,7 +14,6 @@ use to_str::{ToStr,ToStrConsume};
use str;
use str::StrSlice;
use cast;
use old_iter::BaseIter;
use iterator::IteratorUtil;
use vec::{CopyableVector, ImmutableVector, OwnedVector};
use to_bytes::IterBytes;
@ -94,7 +93,7 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
#[inline]
fn is_ascii(&self) -> bool {
for self.each |b| {
for self.iter().advance |b| {
if !b.is_ascii() { return false; }
}
true

View file

@ -12,28 +12,15 @@
#[allow(missing_doc)];
use option::{Some, None};
use cast;
use gc;
use io;
use libc;
use libc::{c_void, c_char, size_t};
use libc::{c_char, size_t};
use repr;
use str;
use unstable::intrinsics;
pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);
// Corresponds to runtime type_desc type
pub struct TypeDesc {
size: uint,
align: uint,
take_glue: uint,
drop_glue: uint,
free_glue: uint
// Remaining fields not listed
}
/// The representation of a Rust closure
pub struct Closure {
code: *(),
@ -51,23 +38,6 @@ pub mod rustrt {
}
}
/**
* Returns a pointer to a type descriptor.
*
* Useful for calling certain function in the Rust runtime or otherwise
* performing dark magick.
*/
#[inline]
pub fn get_type_desc<T>() -> *TypeDesc {
unsafe { intrinsics::get_tydesc::<T>() as *TypeDesc }
}
/// Returns a pointer to a type descriptor.
#[inline]
pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
get_type_desc::<T>()
}
/// Returns the size of a type
#[inline]
pub fn size_of<T>() -> uint {
@ -181,10 +151,9 @@ impl FailWithCause for &'static str {
// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
use cell::Cell;
use option::Option;
use either::Left;
use rt::{context, OldTaskContext, TaskContext};
use rt::task::{Task, Unwinder};
use rt::task::Task;
use rt::local::Local;
use rt::logging::Logger;

View file

@ -142,7 +142,7 @@ unsafe fn local_data_lookup<T: 'static>(
-> Option<(uint, *libc::c_void)> {
let key_value = key_to_key_value(key);
let map_pos = (*map).position(|entry|
let map_pos = (*map).iter().position_(|entry|
match *entry {
Some((k,_,_)) => k == key_value,
None => false
@ -215,7 +215,7 @@ pub unsafe fn local_set<T: 'static>(
}
None => {
// Find an empty slot. If not, grow the vector.
match (*map).position(|x| x.is_none()) {
match (*map).iter().position_(|x| x.is_none()) {
Some(empty_index) => { map[empty_index] = new_entry; }
None => { map.push(new_entry); }
}

View file

@ -353,7 +353,7 @@ impl TaskBuilder {
}
/// Runs a task, while transfering ownership of one argument to the child.
pub fn spawn_with<A:Owned>(&mut self, arg: A, f: ~fn(v: A)) {
pub fn spawn_with<A:Send>(&mut self, arg: A, f: ~fn(v: A)) {
let arg = Cell::new(arg);
do self.spawn {
f(arg.take());
@ -373,7 +373,7 @@ impl TaskBuilder {
* # Failure
* Fails if a future_result was already set for this task.
*/
pub fn try<T:Owned>(&mut self, f: ~fn() -> T) -> Result<T,()> {
pub fn try<T:Send>(&mut self, f: ~fn() -> T) -> Result<T,()> {
let (po, ch) = stream::<T>();
let mut result = None;
@ -445,7 +445,7 @@ pub fn spawn_supervised(f: ~fn()) {
task.spawn(f)
}
pub fn spawn_with<A:Owned>(arg: A, f: ~fn(v: A)) {
pub fn spawn_with<A:Send>(arg: A, f: ~fn(v: A)) {
/*!
* Runs a task, while transfering ownership of one argument to the
* child.
@ -478,7 +478,7 @@ pub fn spawn_sched(mode: SchedMode, f: ~fn()) {
task.spawn(f)
}
pub fn try<T:Owned>(f: ~fn() -> T) -> Result<T,()> {
pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
/*!
* Execute a function in another task and return either the return value
* of the function or result::err.
@ -923,17 +923,15 @@ fn test_spawn_sched_blocking() {
let lock = testrt::rust_dbg_lock_create();
do spawn_sched(SingleThreaded) {
unsafe {
testrt::rust_dbg_lock_lock(lock);
testrt::rust_dbg_lock_lock(lock);
start_ch.send(());
start_ch.send(());
// Block the scheduler thread
testrt::rust_dbg_lock_wait(lock);
testrt::rust_dbg_lock_unlock(lock);
// Block the scheduler thread
testrt::rust_dbg_lock_wait(lock);
testrt::rust_dbg_lock_unlock(lock);
fin_ch.send(());
}
fin_ch.send(());
};
// Wait until the other task has its lock

View file

@ -91,8 +91,8 @@ use uint;
use util;
use unstable::sync::{Exclusive, exclusive};
use rt::local::Local;
use iterator::{IteratorUtil};
use rt::task::Task;
use iterator::IteratorUtil;
#[cfg(test)] use task::default_task_opts;
#[cfg(test)] use comm;
@ -112,7 +112,7 @@ fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
assert!(was_present);
}
pub fn taskset_each(tasks: &TaskSet, blk: &fn(v: *rust_task) -> bool) -> bool {
tasks.each(|k| blk(*k))
tasks.iter().advance(|k| blk(*k))
}
// One of these per group of linked-failure tasks.
@ -130,7 +130,7 @@ type TaskGroupInner<'self> = &'self mut Option<TaskGroupData>;
// A taskgroup is 'dead' when nothing can cause it to fail; only members can.
fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
(&const tg.members).is_empty()
tg.members.is_empty()
}
// A list-like structure by which taskgroups keep track of all ancestor groups
@ -231,11 +231,15 @@ fn each_ancestor(list: &mut AncestorList,
// 'do_continue' - Did the forward_blk succeed at this point? (i.e.,
// should we recurse? or should our callers unwind?)
let forward_blk = Cell::new(forward_blk);
// The map defaults to None, because if ancestors is None, we're at
// the end of the list, which doesn't make sense to coalesce.
return do (**ancestors).map_default((None,false)) |ancestor_arc| {
// NB: Takes a lock! (this ancestor node)
do access_ancestors(ancestor_arc) |nobe| {
// Argh, but we couldn't give it to coalesce() otherwise.
let forward_blk = forward_blk.take();
// Check monotonicity
assert!(last_generation > nobe.generation);
/*##########################################################*
@ -318,7 +322,7 @@ struct TCB {
impl Drop for TCB {
// Runs on task exit.
fn finalize(&self) {
fn drop(&self) {
unsafe {
// FIXME(#4330) Need self by value to get mutability.
let this: &mut TCB = transmute(self);
@ -373,7 +377,7 @@ struct AutoNotify {
}
impl Drop for AutoNotify {
fn finalize(&self) {
fn drop(&self) {
let result = if self.failed { Failure } else { Success };
self.notify_chan.send(result);
}
@ -610,11 +614,8 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
rtdebug!("spawn about to take scheduler");
let mut sched = Local::take::<Scheduler>();
let sched = Local::take::<Scheduler>();
rtdebug!("took sched in spawn");
// let task = ~Coroutine::with_task(&mut sched.stack_pool,
// task, f);
// let task = ~Task::new_root(&mut sched.stack_pool, f);
sched.schedule_task(task);
}
@ -669,7 +670,8 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
let child_data = Cell::new((notify_chan, child_arc, ancestors));
let result: ~fn() = || {
// Agh. Get move-mode items into the closure. FIXME (#2829)
let mut (notify_chan, child_arc, ancestors) = child_data.take();
let (notify_chan, child_arc, ancestors) = child_data.take();
let mut ancestors = ancestors;
// Child task runs this code.
// Even if the below code fails to kick the child off, we must

View file

@ -17,9 +17,10 @@ The `ToBytes` and `IterBytes` traits
use cast;
use io;
use io::Writer;
use iterator::IteratorUtil;
use option::{None, Option, Some};
use old_iter::BaseIter;
use str::StrSlice;
use vec::ImmutableVector;
pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool;
@ -223,7 +224,7 @@ impl IterBytes for f64 {
impl<'self,A:IterBytes> IterBytes for &'self [A] {
#[inline]
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
self.each(|elt| elt.iter_bytes(lsb0, |b| f(b)))
self.iter().advance(|elt| elt.iter_bytes(lsb0, |b| f(b)))
}
}
@ -231,7 +232,8 @@ impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) {
#[inline]
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
match *self {
(ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) }
(ref a, ref b) => { a.iter_bytes(lsb0, |b| f(b)) &&
b.iter_bytes(lsb0, |b| f(b)) }
}
}
}
@ -241,7 +243,9 @@ impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) {
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
match *self {
(ref a, ref b, ref c) => {
a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f)
a.iter_bytes(lsb0, |b| f(b)) &&
b.iter_bytes(lsb0, |b| f(b)) &&
c.iter_bytes(lsb0, |b| f(b))
}
}
}
@ -295,7 +299,7 @@ impl<A:IterBytes> IterBytes for Option<A> {
#[inline]
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
match *self {
Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f),
Some(ref a) => 0u8.iter_bytes(lsb0, |b| f(b)) && a.iter_bytes(lsb0, |b| f(b)),
None => 1u8.iter_bytes(lsb0, f)
}
}

View file

@ -17,10 +17,10 @@ The `ToStr` trait for converting to strings
use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use container::Map;
use hash::Hash;
use iterator::IteratorUtil;
use cmp::Eq;
use old_iter::BaseIter;
use vec::ImmutableVector;
/// A generic trait for converting a value to a string
pub trait ToStr {
@ -53,8 +53,9 @@ impl<A:ToStr> ToStr for (A,) {
impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"{", true);
for self.each |key, value| {
let mut acc = ~"{";
let mut first = true;
for self.iter().advance |(key, value)| {
if first {
first = false;
}
@ -73,8 +74,9 @@ impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"{", true);
for self.each |element| {
let mut acc = ~"{";
let mut first = true;
for self.iter().advance |element| {
if first {
first = false;
}
@ -121,8 +123,9 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
impl<'self,A:ToStr> ToStr for &'self [A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
for self.each |elt| {
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
}
@ -139,8 +142,9 @@ impl<'self,A:ToStr> ToStr for &'self [A] {
impl<A:ToStr> ToStr for ~[A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
for self.each |elt| {
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
}
@ -157,8 +161,9 @@ impl<A:ToStr> ToStr for ~[A] {
impl<A:ToStr> ToStr for @[A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
for self.each |elt| {
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
}
@ -177,7 +182,7 @@ impl<A:ToStr> ToStr for @[A] {
mod tests {
use hashmap::HashMap;
use hashmap::HashSet;
use container::Set;
use container::{Set, Map};
#[test]
fn test_simple_types() {
assert_eq!(1i.to_str(), ~"1");

View file

@ -35,11 +35,11 @@ pub struct TrieMap<T> {
impl<T> Container for TrieMap<T> {
/// Return the number of elements in the map
#[inline]
fn len(&const self) -> uint { self.length }
fn len(&self) -> uint { self.length }
/// Return true if the map contains no elements
#[inline]
fn is_empty(&const self) -> bool { self.len() == 0 }
fn is_empty(&self) -> bool { self.len() == 0 }
}
impl<T> Mutable for TrieMap<T> {
@ -58,30 +58,6 @@ impl<T> Map<uint, T> for TrieMap<T> {
self.find(key).is_some()
}
/// Visit all key-value pairs in order
#[inline]
fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
self.root.each(f)
}
/// Visit all keys in order
#[inline]
fn each_key(&self, f: &fn(&uint) -> bool) -> bool {
self.each(|k, _| f(k))
}
/// Visit all values in order
#[inline]
fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool {
self.each(|_, v| f(v))
}
/// Iterate over the map and mutate the contained values
#[inline]
fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
self.root.mutate_values(f)
}
/// Return a reference to the value corresponding to the key
#[inline]
fn find<'a>(&'a self, key: &uint) -> Option<&'a T> {
@ -158,6 +134,30 @@ impl<T> TrieMap<T> {
self.root.each_reverse(f)
}
/// Visit all key-value pairs in order
#[inline]
pub fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
self.root.each(f)
}
/// Visit all keys in order
#[inline]
pub fn each_key(&self, f: &fn(&uint) -> bool) -> bool {
self.each(|k, _| f(k))
}
/// Visit all values in order
#[inline]
pub fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool {
self.each(|_, v| f(v))
}
/// Iterate over the map and mutate the contained values
#[inline]
pub fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
self.root.mutate_values(f)
}
/// Visit all keys in reverse order
#[inline]
pub fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool {
@ -176,30 +176,14 @@ pub struct TrieSet {
priv map: TrieMap<()>
}
impl BaseIter<uint> for TrieSet {
/// Visit all values in order
#[inline]
fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) }
#[inline]
fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl ReverseIter<uint> for TrieSet {
/// Visit all values in reverse order
#[inline]
fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool {
self.map.each_key_reverse(f)
}
}
impl Container for TrieSet {
/// Return the number of elements in the set
#[inline]
fn len(&const self) -> uint { self.map.len() }
fn len(&self) -> uint { self.map.len() }
/// Return true if the set contains no elements
#[inline]
fn is_empty(&const self) -> bool { self.map.is_empty() }
fn is_empty(&self) -> bool { self.map.is_empty() }
}
impl Mutable for TrieSet {
@ -234,6 +218,16 @@ impl TrieSet {
pub fn remove(&mut self, value: &uint) -> bool {
self.map.remove(value)
}
/// Visit all values in order
#[inline]
pub fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) }
/// Visit all values in reverse order
#[inline]
pub fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool {
self.map.each_key_reverse(f)
}
}
struct TrieNode<T> {
@ -257,7 +251,7 @@ impl<T> TrieNode<T> {
fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
for uint::range(0, self.children.len()) |idx| {
match self.children[idx] {
Internal(ref x) => if !x.each(f) { return false },
Internal(ref x) => if !x.each(|i,t| f(i,t)) { return false },
External(k, ref v) => if !f(&k, v) { return false },
Nothing => ()
}
@ -268,7 +262,7 @@ impl<T> TrieNode<T> {
fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
for uint::range_rev(self.children.len(), 0) |idx| {
match self.children[idx - 1] {
Internal(ref x) => if !x.each_reverse(f) { return false },
Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false },
External(k, ref v) => if !f(&k, v) { return false },
Nothing => ()
}
@ -279,7 +273,7 @@ impl<T> TrieNode<T> {
fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
for self.children.mut_iter().advance |child| {
match *child {
Internal(ref mut x) => if !x.mutate_values(f) {
Internal(ref mut x) => if !x.mutate_values(|i,t| f(i,t)) {
return false
},
External(k, ref mut v) => if !f(&k, v) { return false },
@ -373,7 +367,7 @@ pub fn check_integrity<T>(trie: &TrieNode<T>) {
let mut sum = 0;
for trie.children.each |x| {
for trie.children.iter().advance |x| {
match *x {
Nothing => (),
Internal(ref y) => {

View file

@ -14,6 +14,8 @@
use kinds::Copy;
use vec;
use vec::ImmutableVector;
use iterator::IteratorUtil;
pub use self::inner::*;
@ -96,7 +98,7 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) {
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
vec::map_zip(*a, *b, f)
a.iter().zip(b.iter()).transform(|(aa, bb)| f(aa, bb)).collect()
}
}
}
@ -116,7 +118,7 @@ impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
vec::map_zip(*a, *b, f)
a.iter().zip(b.iter()).transform(|(aa, bb)| f(aa, bb)).collect()
}
}
}

View file

@ -16,9 +16,9 @@ pub mod general_category {
fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
use cmp::{Equal, Less, Greater};
use vec::bsearch;
use vec::ImmutableVector;
use option::None;
(do bsearch(r) |&(lo,hi)| {
(do r.bsearch |&(lo,hi)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
@ -1447,15 +1447,13 @@ pub mod general_category {
}
}
pub mod derived_property {
fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
use cmp::{Equal, Less, Greater};
use vec::bsearch;
use vec::ImmutableVector;
use option::None;
(do bsearch(r) |&(lo,hi)| {
(do r.bsearch |&(lo,hi)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
@ -2641,4 +2639,5 @@ pub mod derived_property {
pub fn XID_Start(c: char) -> bool {
bsearch_range_table(c, XID_Start_table)
}
}

View file

@ -62,6 +62,7 @@ pub struct AtomicPtr<T> {
/**
* An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
*/
#[unsafe_no_drop_flag]
pub struct AtomicOption<T> {
priv p: *mut c_void
}
@ -275,7 +276,7 @@ impl<T> AtomicOption<T> {
#[unsafe_destructor]
impl<T> Drop for AtomicOption<T> {
fn finalize(&self) {
fn drop(&self) {
// This will ensure that the contained data is
// destroyed, unless it's null.
unsafe {

View file

@ -25,7 +25,7 @@ use result::*;
pub struct DynamicLibrary { priv handle: *libc::c_void }
impl Drop for DynamicLibrary {
fn finalize(&self) {
fn drop(&self) {
match do dl::check_for_errors_in {
unsafe {
dl::close(self.handle)
@ -164,7 +164,6 @@ mod dl {
use libc;
use path;
use ptr;
use str;
use task;
use result::*;
@ -175,7 +174,7 @@ mod dl {
}
pub unsafe fn open_internal() -> *libc::c_void {
let mut handle = ptr::null();
let handle = ptr::null();
GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
handle
}

View file

@ -1,83 +0,0 @@
// 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.
use sys::{TypeDesc, size_of};
use libc::{c_void, size_t};
use c_malloc = libc::malloc;
use c_free = libc::free;
use managed::raw::{BoxHeaderRepr, BoxRepr};
use cast::transmute;
use unstable::intrinsics::{atomic_xadd,atomic_xsub};
use ptr::null;
use intrinsic::TyDesc;
pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
assert!(td.is_not_null());
let total_size = get_box_size(size, (*td).align);
let p = c_malloc(total_size as size_t);
assert!(p.is_not_null());
// FIXME #3475: Converting between our two different tydesc types
let td: *TyDesc = transmute(td);
let box: &mut BoxRepr = transmute(p);
box.header.ref_count = -1; // Exchange values not ref counted
box.header.type_desc = td;
box.header.prev = null();
box.header.next = null();
let exchange_count = &mut *rust_get_exchange_count_ptr();
atomic_xadd(exchange_count, 1);
return transmute(box);
}
/**
Thin wrapper around libc::malloc, none of the box header
stuff in exchange_alloc::malloc
*/
pub unsafe fn malloc_raw(size: uint) -> *c_void {
let p = c_malloc(size as size_t);
if p.is_null() {
fail!("Failure in malloc_raw: result ptr is null");
}
p
}
pub unsafe fn free(ptr: *c_void) {
let exchange_count = &mut *rust_get_exchange_count_ptr();
atomic_xsub(exchange_count, 1);
assert!(ptr.is_not_null());
c_free(ptr);
}
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
pub unsafe fn free_raw(ptr: *c_void) {
c_free(ptr);
}
fn get_box_size(body_size: uint, body_align: uint) -> uint {
let header_size = size_of::<BoxHeaderRepr>();
// FIXME (#2699): This alignment calculation is suspicious. Is it right?
let total_size = align_to(header_size, body_align) + body_size;
return total_size;
}
// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
// of two.
fn align_to(size: uint, align: uint) -> uint {
assert!(align != 0);
(size + align - 1) & !(align - 1)
}
extern {
#[rust_stack]
fn rust_get_exchange_count_ptr() -> *mut int;
}

View file

@ -94,6 +94,7 @@ use iterator::IteratorUtil;
#[doc(hidden)]
pub mod ct {
use char;
use container::Container;
use prelude::*;
use str;
@ -350,7 +351,7 @@ pub mod ct {
#[test]
fn test_parse_flags() {
fn pack(fs: &[Flag]) -> uint {
fs.foldl(0, |&p, &f| p | (1 << f as uint))
fs.iter().fold(0, |p, &f| p | (1 << f as uint))
}
fn test(s: &str, flags: &[Flag], next: uint) {

View file

@ -64,7 +64,7 @@ struct Finallyalizer<'self> {
#[unsafe_destructor]
impl<'self> Drop for Finallyalizer<'self> {
fn finalize(&self) {
fn drop(&self) {
(self.dtor)();
}
}

View file

@ -27,7 +27,7 @@ avoid hitting the mutex.
use cast::{transmute};
use clone::Clone;
use kinds::Owned;
use kinds::Send;
use libc::{c_void};
use option::{Option, Some, None};
use ops::Drop;
@ -43,7 +43,7 @@ use sys::Closure;
pub type GlobalDataKey<'self,T> = &'self fn(v: T);
pub unsafe fn global_data_clone_create<T:Owned + Clone>(
pub unsafe fn global_data_clone_create<T:Send + Clone>(
key: GlobalDataKey<T>, create: &fn() -> ~T) -> T {
/*!
* Clone a global value or, if it has not been created,
@ -59,7 +59,7 @@ pub unsafe fn global_data_clone_create<T:Owned + Clone>(
global_data_clone_create_(key_ptr(key), create)
}
unsafe fn global_data_clone_create_<T:Owned + Clone>(
unsafe fn global_data_clone_create_<T:Send + Clone>(
key: uint, create: &fn() -> ~T) -> T {
let mut clone_value: Option<T> = None;
@ -79,13 +79,13 @@ unsafe fn global_data_clone_create_<T:Owned + Clone>(
return clone_value.unwrap();
}
unsafe fn global_data_modify<T:Owned>(
unsafe fn global_data_modify<T:Send>(
key: GlobalDataKey<T>, op: &fn(Option<~T>) -> Option<~T>) {
global_data_modify_(key_ptr(key), op)
}
unsafe fn global_data_modify_<T:Owned>(
unsafe fn global_data_modify_<T:Send>(
key: uint, op: &fn(Option<~T>) -> Option<~T>) {
let mut old_dtor = None;
@ -124,7 +124,7 @@ unsafe fn global_data_modify_<T:Owned>(
}
}
pub unsafe fn global_data_clone<T:Owned + Clone>(
pub unsafe fn global_data_clone<T:Send + Clone>(
key: GlobalDataKey<T>) -> Option<T> {
let mut maybe_clone: Option<T> = None;
do global_data_modify(key) |current| {
@ -147,7 +147,7 @@ struct GlobalState {
}
impl Drop for GlobalState {
fn finalize(&self) {
fn drop(&self) {
for self.map.each_value |v| {
match v {
&(_, ref dtor) => (*dtor)()
@ -220,7 +220,7 @@ fn get_global_state() -> Exclusive<GlobalState> {
}
}
fn key_ptr<T:Owned>(key: GlobalDataKey<T>) -> uint {
fn key_ptr<T:Send>(key: GlobalDataKey<T>) -> uint {
unsafe {
let closure: Closure = transmute(key);
return transmute(closure.code);

View file

@ -32,6 +32,130 @@ A quick refresher on memory ordering:
*/
// This is needed to prevent duplicate lang item definitions.
#[cfg(test)]
pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
#[cfg(not(stage0))]
pub type GlueFn = extern "Rust" fn(*i8);
#[cfg(stage0)]
pub type GlueFn = extern "Rust" fn(**TyDesc, *i8);
// NB: this has to be kept in sync with the Rust ABI.
#[lang="ty_desc"]
#[cfg(not(test))]
pub struct TyDesc {
size: uint,
align: uint,
take_glue: GlueFn,
drop_glue: GlueFn,
free_glue: GlueFn,
visit_glue: GlueFn,
}
#[lang="opaque"]
#[cfg(not(test))]
pub enum Opaque { }
#[lang="ty_visitor"]
#[cfg(not(test))]
pub trait TyVisitor {
fn visit_bot(&self) -> bool;
fn visit_nil(&self) -> bool;
fn visit_bool(&self) -> bool;
fn visit_int(&self) -> bool;
fn visit_i8(&self) -> bool;
fn visit_i16(&self) -> bool;
fn visit_i32(&self) -> bool;
fn visit_i64(&self) -> bool;
fn visit_uint(&self) -> bool;
fn visit_u8(&self) -> bool;
fn visit_u16(&self) -> bool;
fn visit_u32(&self) -> bool;
fn visit_u64(&self) -> bool;
fn visit_float(&self) -> bool;
fn visit_f32(&self) -> bool;
fn visit_f64(&self) -> bool;
fn visit_char(&self) -> bool;
fn visit_str(&self) -> bool;
fn visit_estr_box(&self) -> bool;
fn visit_estr_uniq(&self) -> bool;
fn visit_estr_slice(&self) -> bool;
fn visit_estr_fixed(&self, n: uint, sz: uint, align: uint) -> bool;
fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_enter_rec(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_rec_field(&self, i: uint, name: &str,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_leave_rec(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_class(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_class_field(&self, i: uint, name: &str,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_leave_class(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_tup(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool;
fn visit_leave_tup(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_enum(&self, n_variants: uint,
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
sz: uint, align: uint) -> bool;
fn visit_enter_enum_variant(&self, variant: uint,
disr_val: int,
n_fields: uint,
name: &str) -> bool;
fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool;
fn visit_leave_enum_variant(&self, variant: uint,
disr_val: int,
n_fields: uint,
name: &str) -> bool;
fn visit_leave_enum(&self, n_variants: uint,
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
sz: uint, align: uint) -> bool;
fn visit_enter_fn(&self, purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool;
fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool;
fn visit_leave_fn(&self, purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_trait(&self) -> bool;
fn visit_var(&self) -> bool;
fn visit_var_integral(&self) -> bool;
fn visit_param(&self, i: uint) -> bool;
fn visit_self(&self) -> bool;
fn visit_type(&self) -> bool;
fn visit_opaque_box(&self) -> bool;
fn visit_constr(&self, inner: *TyDesc) -> bool;
fn visit_closure_ptr(&self, ck: uint) -> bool;
}
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
@ -42,22 +166,32 @@ pub extern "rust-intrinsic" {
/// Atomic compare and exchange, release ordering.
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_acqrel(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_relaxed(dst: &mut int, old: int, src: int) -> int;
/// Atomic load, sequentially consistent.
pub fn atomic_load(src: &int) -> int;
/// Atomic load, acquire ordering.
pub fn atomic_load_acq(src: &int) -> int;
pub fn atomic_load_relaxed(src: &int) -> int;
/// Atomic store, sequentially consistent.
pub fn atomic_store(dst: &mut int, val: int);
/// Atomic store, release ordering.
pub fn atomic_store_rel(dst: &mut int, val: int);
pub fn atomic_store_relaxed(dst: &mut int, val: int);
/// Atomic exchange, sequentially consistent.
pub fn atomic_xchg(dst: &mut int, src: int) -> int;
/// Atomic exchange, acquire ordering.
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
/// Atomic exchange, release ordering.
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xchg_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_xchg_relaxed(dst: &mut int, src: int) -> int;
/// Atomic addition, sequentially consistent.
pub fn atomic_xadd(dst: &mut int, src: int) -> int;
@ -65,6 +199,8 @@ pub extern "rust-intrinsic" {
pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
/// Atomic addition, release ordering.
pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xadd_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_xadd_relaxed(dst: &mut int, src: int) -> int;
/// Atomic subtraction, sequentially consistent.
pub fn atomic_xsub(dst: &mut int, src: int) -> int;
@ -72,6 +208,56 @@ pub extern "rust-intrinsic" {
pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
/// Atomic subtraction, release ordering.
pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xsub_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_xsub_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_and(dst: &mut int, src: int) -> int;
pub fn atomic_and_acq(dst: &mut int, src: int) -> int;
pub fn atomic_and_rel(dst: &mut int, src: int) -> int;
pub fn atomic_and_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_and_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_nand(dst: &mut int, src: int) -> int;
pub fn atomic_nand_acq(dst: &mut int, src: int) -> int;
pub fn atomic_nand_rel(dst: &mut int, src: int) -> int;
pub fn atomic_nand_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_nand_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_or(dst: &mut int, src: int) -> int;
pub fn atomic_or_acq(dst: &mut int, src: int) -> int;
pub fn atomic_or_rel(dst: &mut int, src: int) -> int;
pub fn atomic_or_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_or_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_xor(dst: &mut int, src: int) -> int;
pub fn atomic_xor_acq(dst: &mut int, src: int) -> int;
pub fn atomic_xor_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xor_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_xor_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_max(dst: &mut int, src: int) -> int;
pub fn atomic_max_acq(dst: &mut int, src: int) -> int;
pub fn atomic_max_rel(dst: &mut int, src: int) -> int;
pub fn atomic_max_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_max_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_min(dst: &mut int, src: int) -> int;
pub fn atomic_min_acq(dst: &mut int, src: int) -> int;
pub fn atomic_min_rel(dst: &mut int, src: int) -> int;
pub fn atomic_min_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_min_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_umin(dst: &mut int, src: int) -> int;
pub fn atomic_umin_acq(dst: &mut int, src: int) -> int;
pub fn atomic_umin_rel(dst: &mut int, src: int) -> int;
pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int;
pub fn atomic_umax(dst: &mut int, src: int) -> int;
pub fn atomic_umax_acq(dst: &mut int, src: int) -> int;
pub fn atomic_umax_rel(dst: &mut int, src: int) -> int;
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
/// The size of a type in bytes.
///
@ -97,6 +283,9 @@ pub extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> uint;
/// Get a static pointer to a type descriptor.
#[cfg(not(stage0))]
pub fn get_tydesc<T>() -> *TyDesc;
#[cfg(stage0)]
pub fn get_tydesc<T>() -> *();
/// Create a value initialized to zero.
@ -119,9 +308,12 @@ pub extern "rust-intrinsic" {
/// Returns `true` if a type requires drop glue.
pub fn needs_drop<T>() -> bool;
// XXX: intrinsic uses legacy modes and has reference to TyDesc
// and TyVisitor which are in librustc
//fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> ();
/// Returns `true` if a type is managed (will be allocated on the local heap)
#[cfg(not(stage0))]
pub fn contains_managed<T>() -> bool;
#[cfg(not(stage0))]
pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
pub fn frame_address(f: &once fn(*u8));

View file

@ -10,27 +10,21 @@
//! Runtime calls emitted by the compiler.
use iterator::IteratorUtil;
use uint;
use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO};
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use str;
use sys;
use rt::{context, OldTaskContext};
use rt::task::Task;
use rt::local::Local;
use option::{Option, Some, None};
use io;
use rt::global_heap;
use rt::borrowck;
use borrow::to_uint;
#[allow(non_camel_case_types)]
pub type rust_task = c_void;
pub mod rustrt {
use unstable::lang::rust_task;
use libc::{c_void, c_char, uintptr_t};
use libc::{c_char, uintptr_t};
pub extern {
#[rust_stack]
@ -66,22 +60,6 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
}
}
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
transmute(global_heap::malloc(transmute(td), transmute(size)))
}
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="exchange_free"]
#[inline]
pub unsafe fn exchange_free(ptr: *c_char) {
global_heap::free(transmute(ptr))
}
#[lang="malloc"]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
match context() {

View file

@ -17,7 +17,7 @@ use unstable::finally::Finally;
use unstable::intrinsics;
use ops::Drop;
use clone::Clone;
use kinds::Owned;
use kinds::Send;
/// An atomically reference counted pointer.
///
@ -31,7 +31,7 @@ struct AtomicRcBoxData<T> {
data: Option<T>,
}
impl<T: Owned> UnsafeAtomicRcBox<T> {
impl<T: Send> UnsafeAtomicRcBox<T> {
pub fn new(data: T) -> UnsafeAtomicRcBox<T> {
unsafe {
let data = ~AtomicRcBoxData { count: 1, data: Some(data) };
@ -61,7 +61,7 @@ impl<T: Owned> UnsafeAtomicRcBox<T> {
}
}
impl<T: Owned> Clone for UnsafeAtomicRcBox<T> {
impl<T: Send> Clone for UnsafeAtomicRcBox<T> {
fn clone(&self) -> UnsafeAtomicRcBox<T> {
unsafe {
let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
@ -75,7 +75,7 @@ impl<T: Owned> Clone for UnsafeAtomicRcBox<T> {
#[unsafe_destructor]
impl<T> Drop for UnsafeAtomicRcBox<T>{
fn finalize(&self) {
fn drop(&self) {
unsafe {
do task::unkillable {
let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
@ -102,7 +102,7 @@ struct LittleLock {
}
impl Drop for LittleLock {
fn finalize(&self) {
fn drop(&self) {
unsafe {
rust_destroy_little_lock(self.l);
}
@ -144,7 +144,7 @@ pub struct Exclusive<T> {
x: UnsafeAtomicRcBox<ExData<T>>
}
pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
pub fn exclusive<T:Send>(user_data: T) -> Exclusive<T> {
let data = ExData {
lock: LittleLock(),
failed: false,
@ -155,14 +155,14 @@ pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
}
}
impl<T:Owned> Clone for Exclusive<T> {
impl<T:Send> Clone for Exclusive<T> {
// Duplicate an exclusive ARC, as std::arc::clone.
fn clone(&self) -> Exclusive<T> {
Exclusive { x: self.x.clone() }
}
}
impl<T:Owned> Exclusive<T> {
impl<T:Send> Exclusive<T> {
// Exactly like std::arc::mutex_arc,access(), but with the little_lock
// instead of a proper mutex. Same reason for being unsafe.
//
@ -282,7 +282,7 @@ mod tests {
}
};
for futures.each |f| { f.recv() }
for futures.iter().advance |f| { f.recv() }
do total.with |total| {
assert!(**total == num_tasks * count)

View file

@ -75,18 +75,14 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
}
/// A non-copyable dummy type.
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
#[unsafe_no_drop_flag]
pub struct NonCopyable;
impl NonCopyable {
/// Creates a dummy non-copyable structure and returns it for use.
pub fn new() -> NonCopyable { NonCopyable }
}
impl Drop for NonCopyable {
fn finalize(&self) { }
fn drop(&self) { }
}
/// A type with no inhabitants
pub enum Void { }
@ -130,39 +126,73 @@ pub fn unreachable() -> ! {
#[cfg(test)]
mod tests {
use super::*;
use option::{None, Some};
use util::{Void, NonCopyable, id, replace, swap};
use either::{Either, Left, Right};
use sys::size_of;
use kinds::Drop;
#[test]
pub fn identity_crisis() {
fn identity_crisis() {
// Writing a test for the identity function. How did it come to this?
let x = ~[(5, false)];
//FIXME #3387 assert!(x.eq(id(copy x)));
let y = copy x;
assert!(x.eq(&id(y)));
}
#[test]
pub fn test_swap() {
fn test_swap() {
let mut x = 31337;
let mut y = 42;
swap(&mut x, &mut y);
assert_eq!(x, 42);
assert_eq!(y, 31337);
}
#[test]
pub fn test_replace() {
let mut x = Some(NonCopyable::new());
fn test_replace() {
let mut x = Some(NonCopyable);
let y = replace(&mut x, None);
assert!(x.is_none());
assert!(y.is_some());
}
#[test]
pub fn test_uninhabited() {
fn test_uninhabited() {
let could_only_be_coin : Either <Void, ()> = Right (());
match could_only_be_coin {
Right (coin) => coin,
Left (is_void) => is_void.uninhabited ()
}
}
#[test]
fn test_noncopyable() {
assert_eq!(size_of::<NonCopyable>(), 0);
// verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
// NOTE: uncomment after snapshot, will not parse yet
//static mut did_run: bool = false;
struct Foo { five: int }
impl Drop for Foo {
fn drop(&self) {
assert_eq!(self.five, 5);
// NOTE: uncomment after snapshot, will not parse yet
//unsafe {
//did_run = true;
//}
}
}
{
let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
}
// NOTE: uncomment after snapshot, will not parse yet
//unsafe { assert_eq!(did_run, true); }
}
}

File diff suppressed because it is too large Load diff