diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-07-02 17:36:58 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-07-03 14:49:13 -0700 |
| commit | 1098d6980b13dc00e3f20deae987423e3bcae9ce (patch) | |
| tree | 4d6cfd62f1d0d3298d4144aebd6c81c91edea9dc /src/libstd | |
| parent | f8a4d09f7efb618ca3f8b70374e158504cb33cb0 (diff) | |
| parent | ab34864a304fa364dc91bf16988e272e93de8d62 (diff) | |
| download | rust-1098d6980b13dc00e3f20deae987423e3bcae9ce.tar.gz rust-1098d6980b13dc00e3f20deae987423e3bcae9ce.zip | |
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
Diffstat (limited to 'src/libstd')
81 files changed, 3654 insertions, 3300 deletions
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 18dfbd82c5a..75d0fe7a0b2 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -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; diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index e1d2b246dd3..53ea11f2b05 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -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> { diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 797fd9e8c02..6a9555f4efc 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -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"); } diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index 36c1fdf781b..abda76c9ca6 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -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); } } diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 5ec594cef7e..947aa5708c2 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -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() } diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index 00c33c8ab32..1bb0ff044fe 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -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> diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs index 2f150a0d1b2..04f2d815d08 100644 --- a/src/libstd/condition.rs +++ b/src/libstd/condition.rs @@ -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); diff --git a/src/libstd/container.rs b/src/libstd/container.rs index c1b656f1cd9..d6f4c26715a 100644 --- a/src/libstd/container.rs +++ b/src/libstd/container.rs @@ -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>; diff --git a/src/libstd/either.rs b/src/libstd/either.rs index 681a7fbc821..b6da93f9d40 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -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 */ } diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs index 611b95a7745..c9e33219fa5 100644 --- a/src/libstd/gc.rs +++ b/src/libstd/gc.rs @@ -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,18 +59,12 @@ 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; pub unsafe fn rust_get_stack_segment() -> *StackSegment; @@ -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); } } } diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index 1967a57e867..6c3fcd41ed3 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -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; diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index d05fa63a6f9..85dca1154bc 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -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() { @@ -937,6 +994,19 @@ mod test_set { } #[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(); let mut b = 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()); diff --git a/src/libstd/io.rs b/src/libstd/io.rs index e5e8a4cb601..bdcad15f45c 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -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); diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 7053cbe0df5..4e598a4aa1c 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -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); } } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index eefad1a03dc..77befbf19aa 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -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]); } @@ -984,6 +1149,19 @@ mod tests { } #[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> { if *st < 10 { @@ -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); + } } diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 05c963a32cc..f350e106168 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -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"] diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 07b2ac6ed01..f4ea29b5c05 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -102,10 +102,12 @@ pub use libc::funcs::posix88::stdio::*; pub use libc::funcs::posix88::fcntl::*; pub use libc::funcs::posix88::dirent::*; pub use libc::funcs::posix88::unistd::*; +pub use libc::funcs::posix88::mman::*; pub use libc::funcs::posix01::stat_::*; pub use libc::funcs::posix01::unistd::*; pub use libc::funcs::posix01::glob::*; +pub use libc::funcs::posix01::mman::*; pub use libc::funcs::posix08::unistd::*; pub use libc::funcs::bsd44::*; @@ -257,6 +259,8 @@ pub mod types { pub type intptr_t = int; pub type uintptr_t = uint; } + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "mips")] pub mod posix88 { pub type off_t = i32; pub type dev_t = u64; @@ -268,8 +272,22 @@ pub mod types { pub type mode_t = u32; pub type ssize_t = i32; } + #[cfg(target_arch = "arm")] + pub mod posix88 { + pub type off_t = i32; + pub type dev_t = u32; + pub type ino_t = u32; + pub type pid_t = i32; + pub type uid_t = u32; + pub type gid_t = u32; + pub type useconds_t = u32; + pub type mode_t = u16; + pub type ssize_t = i32; + } + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "mips")] pub mod posix01 { - use libc::types::os::arch::c95::{c_short, c_long, c_ulong, time_t}; + use libc::types::os::arch::c95::{c_short, c_long, time_t}; use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t}; use libc::types::os::arch::posix88::{mode_t, off_t}; use libc::types::os::arch::posix88::{uid_t}; @@ -279,7 +297,6 @@ pub mod types { pub type blkcnt_t = i32; #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] pub struct stat { st_dev: dev_t, __pad1: c_short, @@ -327,6 +344,38 @@ pub mod types { st_pad5: [c_long, ..14], } } + #[cfg(target_arch = "arm")] + pub mod posix01 { + use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t}; + use libc::types::os::arch::c99::{c_longlong, c_ulonglong}; + use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t}; + + pub type nlink_t = u16; + pub type blksize_t = u32; + pub type blkcnt_t = u32; + + pub struct stat { + st_dev: c_ulonglong, + __pad0: [c_uchar, ..4], + __st_ino: ino_t, + st_mode: c_uint, + st_nlink: c_uint, + st_uid: uid_t, + st_gid: gid_t, + st_rdev: c_ulonglong, + __pad3: [c_uchar, ..4], + st_size: c_longlong, + st_blksize: blksize_t, + st_blocks: c_ulonglong, + st_atime: time_t, + st_atime_nsec: c_ulong, + st_mtime: time_t, + st_mtime_nsec: c_ulong, + st_ctime: time_t, + st_ctime_nsec: c_ulong, + st_ino: c_ulonglong + } + } pub mod posix08 {} pub mod bsd44 {} pub mod extra {} @@ -518,7 +567,7 @@ pub mod types { pub mod os { pub mod common { pub mod posix01 { - use libc::types::os::arch::c95::{c_int, c_short}; + use libc::types::os::arch::c95::c_short; use libc::types::os::arch::extra::{int64, time64_t}; use libc::types::os::arch::posix88::{dev_t, ino_t}; use libc::types::os::arch::posix88::mode_t; @@ -855,52 +904,56 @@ pub mod consts { #[cfg(target_os = "win32")] pub mod os { pub mod c95 { - pub static EXIT_FAILURE : int = 1; - pub static EXIT_SUCCESS : int = 0; - pub static RAND_MAX : int = 32767; - pub static EOF : int = -1; - pub static SEEK_SET : int = 0; - pub static SEEK_CUR : int = 1; - pub static SEEK_END : int = 2; - pub static _IOFBF : int = 0; - pub static _IONBF : int = 4; - pub static _IOLBF : int = 64; - pub static BUFSIZ : uint = 512_u; - pub static FOPEN_MAX : uint = 20_u; - pub static FILENAME_MAX : uint = 260_u; - pub static L_tmpnam : uint = 16_u; - pub static TMP_MAX : uint = 32767_u; + use libc::types::os::arch::c95::{c_int, c_uint}; + + pub static EXIT_FAILURE : c_int = 1; + pub static EXIT_SUCCESS : c_int = 0; + pub static RAND_MAX : c_int = 32767; + pub static EOF : c_int = -1; + pub static SEEK_SET : c_int = 0; + pub static SEEK_CUR : c_int = 1; + pub static SEEK_END : c_int = 2; + pub static _IOFBF : c_int = 0; + pub static _IONBF : c_int = 4; + pub static _IOLBF : c_int = 64; + pub static BUFSIZ : c_uint = 512_u32; + pub static FOPEN_MAX : c_uint = 20_u32; + pub static FILENAME_MAX : c_uint = 260_u32; + pub static L_tmpnam : c_uint = 16_u32; + pub static TMP_MAX : c_uint = 32767_u32; } pub mod c99 { } pub mod posix88 { - pub static O_RDONLY : int = 0; - pub static O_WRONLY : int = 1; - pub static O_RDWR : int = 2; - pub static O_APPEND : int = 8; - pub static O_CREAT : int = 256; - pub static O_EXCL : int = 1024; - pub static O_TRUNC : int = 512; - pub static S_IFIFO : int = 4096; - pub static S_IFCHR : int = 8192; - pub static S_IFBLK : int = 12288; - pub static S_IFDIR : int = 16384; - pub static S_IFREG : int = 32768; - pub static S_IFMT : int = 61440; - pub static S_IEXEC : int = 64; - pub static S_IWRITE : int = 128; - pub static S_IREAD : int = 256; - pub static S_IRWXU : int = 448; - pub static S_IXUSR : int = 64; - pub static S_IWUSR : int = 128; - pub static S_IRUSR : int = 256; - pub static F_OK : int = 0; - pub static R_OK : int = 4; - pub static W_OK : int = 2; - pub static X_OK : int = 1; - pub static STDIN_FILENO : int = 0; - pub static STDOUT_FILENO : int = 1; - pub static STDERR_FILENO : int = 2; + use libc::types::os::arch::c95::c_int; + + pub static O_RDONLY : c_int = 0; + pub static O_WRONLY : c_int = 1; + pub static O_RDWR : c_int = 2; + pub static O_APPEND : c_int = 8; + pub static O_CREAT : c_int = 256; + pub static O_EXCL : c_int = 1024; + pub static O_TRUNC : c_int = 512; + pub static S_IFIFO : c_int = 4096; + pub static S_IFCHR : c_int = 8192; + pub static S_IFBLK : c_int = 12288; + pub static S_IFDIR : c_int = 16384; + pub static S_IFREG : c_int = 32768; + pub static S_IFMT : c_int = 61440; + pub static S_IEXEC : c_int = 64; + pub static S_IWRITE : c_int = 128; + pub static S_IREAD : c_int = 256; + pub static S_IRWXU : c_int = 448; + pub static S_IXUSR : c_int = 64; + pub static S_IWUSR : c_int = 128; + pub static S_IRUSR : c_int = 256; + pub static F_OK : c_int = 0; + pub static R_OK : c_int = 4; + pub static W_OK : c_int = 2; + pub static X_OK : c_int = 1; + pub static STDIN_FILENO : c_int = 0; + pub static STDOUT_FILENO : c_int = 1; + pub static STDERR_FILENO : c_int = 2; } pub mod posix01 { } @@ -909,18 +962,19 @@ pub mod consts { pub mod bsd44 { } pub mod extra { + use libc::types::os::arch::c95::c_int; use libc::types::os::arch::extra::{DWORD, BOOL}; pub static TRUE : BOOL = 1; pub static FALSE : BOOL = 0; - pub static O_TEXT : int = 16384; - pub static O_BINARY : int = 32768; - pub static O_NOINHERIT: int = 128; + pub static O_TEXT : c_int = 16384; + pub static O_BINARY : c_int = 32768; + pub static O_NOINHERIT: c_int = 128; - pub static ERROR_SUCCESS : int = 0; - pub static ERROR_INSUFFICIENT_BUFFER : int = 122; - pub static INVALID_HANDLE_VALUE: int = -1; + pub static ERROR_SUCCESS : c_int = 0; + pub static ERROR_INSUFFICIENT_BUFFER : c_int = 122; + pub static INVALID_HANDLE_VALUE: c_int = -1; pub static DELETE : DWORD = 0x00010000; pub static READ_CONTROL : DWORD = 0x00020000; @@ -973,21 +1027,23 @@ pub mod consts { #[cfg(target_os = "android")] pub mod os { pub mod c95 { - pub static EXIT_FAILURE : int = 1; - pub static EXIT_SUCCESS : int = 0; - pub static RAND_MAX : int = 2147483647; - pub static EOF : int = -1; - pub static SEEK_SET : int = 0; - pub static SEEK_CUR : int = 1; - pub static SEEK_END : int = 2; - pub static _IOFBF : int = 0; - pub static _IONBF : int = 2; - pub static _IOLBF : int = 1; - pub static BUFSIZ : uint = 8192_u; - pub static FOPEN_MAX : uint = 16_u; - pub static FILENAME_MAX : uint = 4096_u; - pub static L_tmpnam : uint = 20_u; - pub static TMP_MAX : uint = 238328_u; + use libc::types::os::arch::c95::{c_int, c_uint}; + + pub static EXIT_FAILURE : c_int = 1; + pub static EXIT_SUCCESS : c_int = 0; + pub static RAND_MAX : c_int = 2147483647; + pub static EOF : c_int = -1; + pub static SEEK_SET : c_int = 0; + pub static SEEK_CUR : c_int = 1; + pub static SEEK_END : c_int = 2; + pub static _IOFBF : c_int = 0; + pub static _IONBF : c_int = 2; + pub static _IOLBF : c_int = 1; + pub static BUFSIZ : c_uint = 8192_u32; + pub static FOPEN_MAX : c_uint = 16_u32; + pub static FILENAME_MAX : c_uint = 4096_u32; + pub static L_tmpnam : c_uint = 20_u32; + pub static TMP_MAX : c_uint = 238328_u32; } pub mod c99 { } @@ -995,309 +1051,791 @@ pub mod consts { #[cfg(target_arch = "x86_64")] #[cfg(target_arch = "arm")] pub mod posix88 { - pub static O_RDONLY : int = 0; - pub static O_WRONLY : int = 1; - pub static O_RDWR : int = 2; - pub static O_APPEND : int = 1024; - pub static O_CREAT : int = 64; - pub static O_EXCL : int = 128; - pub static O_TRUNC : int = 512; - pub static S_IFIFO : int = 4096; - pub static S_IFCHR : int = 8192; - pub static S_IFBLK : int = 24576; - pub static S_IFDIR : int = 16384; - pub static S_IFREG : int = 32768; - pub static S_IFMT : int = 61440; - pub static S_IEXEC : int = 64; - pub static S_IWRITE : int = 128; - pub static S_IREAD : int = 256; - pub static S_IRWXU : int = 448; - pub static S_IXUSR : int = 64; - pub static S_IWUSR : int = 128; - pub static S_IRUSR : int = 256; - pub static F_OK : int = 0; - pub static R_OK : int = 4; - pub static W_OK : int = 2; - pub static X_OK : int = 1; - pub static STDIN_FILENO : int = 0; - pub static STDOUT_FILENO : int = 1; - pub static STDERR_FILENO : int = 2; - pub static F_LOCK : int = 1; - pub static F_TEST : int = 3; - pub static F_TLOCK : int = 2; - pub static F_ULOCK : int = 0; - pub static SIGHUP : int = 1; - pub static SIGINT : int = 2; - pub static SIGQUIT : int = 3; - pub static SIGILL : int = 4; - pub static SIGABRT : int = 6; - pub static SIGFPE : int = 8; - pub static SIGKILL : int = 9; - pub static SIGSEGV : int = 11; - pub static SIGPIPE : int = 13; - pub static SIGALRM : int = 14; - pub static SIGTERM : int = 15; + use libc::types::os::arch::c95::c_int; + use libc::types::common::c95::c_void; + + pub static O_RDONLY : c_int = 0; + pub static O_WRONLY : c_int = 1; + pub static O_RDWR : c_int = 2; + pub static O_APPEND : c_int = 1024; + pub static O_CREAT : c_int = 64; + pub static O_EXCL : c_int = 128; + pub static O_TRUNC : c_int = 512; + pub static S_IFIFO : c_int = 4096; + pub static S_IFCHR : c_int = 8192; + pub static S_IFBLK : c_int = 24576; + pub static S_IFDIR : c_int = 16384; + pub static S_IFREG : c_int = 32768; + pub static S_IFMT : c_int = 61440; + pub static S_IEXEC : c_int = 64; + pub static S_IWRITE : c_int = 128; + pub static S_IREAD : c_int = 256; + pub static S_IRWXU : c_int = 448; + pub static S_IXUSR : c_int = 64; + pub static S_IWUSR : c_int = 128; + pub static S_IRUSR : c_int = 256; + pub static F_OK : c_int = 0; + pub static R_OK : c_int = 4; + pub static W_OK : c_int = 2; + pub static X_OK : c_int = 1; + pub static STDIN_FILENO : c_int = 0; + pub static STDOUT_FILENO : c_int = 1; + pub static STDERR_FILENO : c_int = 2; + pub static F_LOCK : c_int = 1; + pub static F_TEST : c_int = 3; + pub static F_TLOCK : c_int = 2; + pub static F_ULOCK : c_int = 0; + pub static SIGHUP : c_int = 1; + pub static SIGINT : c_int = 2; + pub static SIGQUIT : c_int = 3; + pub static SIGILL : c_int = 4; + pub static SIGABRT : c_int = 6; + pub static SIGFPE : c_int = 8; + pub static SIGKILL : c_int = 9; + pub static SIGSEGV : c_int = 11; + pub static SIGPIPE : c_int = 13; + pub static SIGALRM : c_int = 14; + pub static SIGTERM : c_int = 15; + + pub static PROT_NONE : c_int = 0; + pub static PROT_READ : c_int = 1; + pub static PROT_WRITE : c_int = 2; + pub static PROT_EXEC : c_int = 4; + + pub static MAP_FILE : c_int = 0x0000; + pub static MAP_SHARED : c_int = 0x0001; + pub static MAP_PRIVATE : c_int = 0x0002; + pub static MAP_FIXED : c_int = 0x0010; + pub static MAP_ANON : c_int = 0x1000; + + pub static MAP_FAILED : *c_void = -1 as *c_void; + + pub static MCL_CURRENT : c_int = 0x0001; + pub static MCL_FUTURE : c_int = 0x0002; + + pub static MS_ASYNC : c_int = 0x0001; + pub static MS_INVALIDATE : c_int = 0x0002; + pub static MS_SYNC : c_int = 0x0004; } #[cfg(target_arch = "mips")] pub mod posix88 { - pub static O_RDONLY : int = 0; - pub static O_WRONLY : int = 1; - pub static O_RDWR : int = 2; - pub static O_APPEND : int = 8; - pub static O_CREAT : int = 256; - pub static O_EXCL : int = 1024; - pub static O_TRUNC : int = 512; - pub static S_IFIFO : int = 4096; - pub static S_IFCHR : int = 8192; - pub static S_IFBLK : int = 24576; - pub static S_IFDIR : int = 16384; - pub static S_IFREG : int = 32768; - pub static S_IFMT : int = 61440; - pub static S_IEXEC : int = 64; - pub static S_IWRITE : int = 128; - pub static S_IREAD : int = 256; - pub static S_IRWXU : int = 448; - pub static S_IXUSR : int = 64; - pub static S_IWUSR : int = 128; - pub static S_IRUSR : int = 256; - pub static F_OK : int = 0; - pub static R_OK : int = 4; - pub static W_OK : int = 2; - pub static X_OK : int = 1; - pub static STDIN_FILENO : int = 0; - pub static STDOUT_FILENO : int = 1; - pub static STDERR_FILENO : int = 2; - pub static F_LOCK : int = 1; - pub static F_TEST : int = 3; - pub static F_TLOCK : int = 2; - pub static F_ULOCK : int = 0; - pub static SIGHUP : int = 1; - pub static SIGINT : int = 2; - pub static SIGQUIT : int = 3; - pub static SIGILL : int = 4; - pub static SIGABRT : int = 6; - pub static SIGFPE : int = 8; - pub static SIGKILL : int = 9; - pub static SIGSEGV : int = 11; - pub static SIGPIPE : int = 13; - pub static SIGALRM : int = 14; - pub static SIGTERM : int = 15; + use libc::types::os::arch::c95::c_int; + use libc::types::common::c95::c_void; + + pub static O_RDONLY : c_int = 0; + pub static O_WRONLY : c_int = 1; + pub static O_RDWR : c_int = 2; + pub static O_APPEND : c_int = 8; + pub static O_CREAT : c_int = 256; + pub static O_EXCL : c_int = 1024; + pub static O_TRUNC : c_int = 512; + pub static S_IFIFO : c_int = 4096; + pub static S_IFCHR : c_int = 8192; + pub static S_IFBLK : c_int = 24576; + pub static S_IFDIR : c_int = 16384; + pub static S_IFREG : c_int = 32768; + pub static S_IFMT : c_int = 61440; + pub static S_IEXEC : c_int = 64; + pub static S_IWRITE : c_int = 128; + pub static S_IREAD : c_int = 256; + pub static S_IRWXU : c_int = 448; + pub static S_IXUSR : c_int = 64; + pub static S_IWUSR : c_int = 128; + pub static S_IRUSR : c_int = 256; + pub static F_OK : c_int = 0; + pub static R_OK : c_int = 4; + pub static W_OK : c_int = 2; + pub static X_OK : c_int = 1; + pub static STDIN_FILENO : c_int = 0; + pub static STDOUT_FILENO : c_int = 1; + pub static STDERR_FILENO : c_int = 2; + pub static F_LOCK : c_int = 1; + pub static F_TEST : c_int = 3; + pub static F_TLOCK : c_int = 2; + pub static F_ULOCK : c_int = 0; + pub static SIGHUP : c_int = 1; + pub static SIGINT : c_int = 2; + pub static SIGQUIT : c_int = 3; + pub static SIGILL : c_int = 4; + pub static SIGABRT : c_int = 6; + pub static SIGFPE : c_int = 8; + pub static SIGKILL : c_int = 9; + pub static SIGSEGV : c_int = 11; + pub static SIGPIPE : c_int = 13; + pub static SIGALRM : c_int = 14; + pub static SIGTERM : c_int = 15; + + pub static PROT_NONE : c_int = 0; + pub static PROT_READ : c_int = 1; + pub static PROT_WRITE : c_int = 2; + pub static PROT_EXEC : c_int = 4; + + pub static MAP_FILE : c_int = 0x0000; + pub static MAP_SHARED : c_int = 0x0001; + pub static MAP_PRIVATE : c_int = 0x0002; + pub static MAP_FIXED : c_int = 0x0010; + pub static MAP_ANON : c_int = 0x1000; + + pub static MAP_FAILED : *c_void = -1 as *c_void; + + pub static MCL_CURRENT : c_int = 0x0001; + pub static MCL_FUTURE : c_int = 0x0002; + + pub static MS_ASYNC : c_int = 0x0001; + pub static MS_INVALIDATE : c_int = 0x0002; + pub static MS_SYNC : c_int = 0x0004; + + pub static _SC_ARG_MAX : c_int = 0; + pub static _SC_CHILD_MAX : c_int = 1; + pub static _SC_CLK_TCK : c_int = 2; + pub static _SC_NGROUPS_MAX : c_int = 3; + pub static _SC_OPEN_MAX : c_int = 4; + pub static _SC_STREAM_MAX : c_int = 5; + pub static _SC_TZNAME_MAX : c_int = 6; + pub static _SC_JOB_CONTROL : c_int = 7; + pub static _SC_SAVED_IDS : c_int = 8; + pub static _SC_REALTIME_SIGNALS : c_int = 9; + pub static _SC_PRIORITY_SCHEDULING : c_int = 10; + pub static _SC_TIMERS : c_int = 11; + pub static _SC_ASYNCHRONOUS_IO : c_int = 12; + pub static _SC_PRIORITIZED_IO : c_int = 13; + pub static _SC_SYNCHRONIZED_IO : c_int = 14; + pub static _SC_FSYNC : c_int = 15; + pub static _SC_MAPPED_FILES : c_int = 16; + pub static _SC_MEMLOCK : c_int = 17; + pub static _SC_MEMLOCK_RANGE : c_int = 18; + pub static _SC_MEMORY_PROTECTION : c_int = 19; + pub static _SC_MESSAGE_PASSING : c_int = 20; + pub static _SC_SEMAPHORES : c_int = 21; + pub static _SC_SHARED_MEMORY_OBJECTS : c_int = 22; + pub static _SC_AIO_LISTIO_MAX : c_int = 23; + pub static _SC_AIO_MAX : c_int = 24; + pub static _SC_AIO_PRIO_DELTA_MAX : c_int = 25; + pub static _SC_DELAYTIMER_MAX : c_int = 26; + pub static _SC_MQ_OPEN_MAX : c_int = 27; + pub static _SC_VERSION : c_int = 29; + pub static _SC_PAGESIZE : c_int = 30; + pub static _SC_RTSIG_MAX : c_int = 31; + pub static _SC_SEM_NSEMS_MAX : c_int = 32; + pub static _SC_SEM_VALUE_MAX : c_int = 33; + pub static _SC_SIGQUEUE_MAX : c_int = 34; + pub static _SC_TIMER_MAX : c_int = 35; + pub static _SC_BC_BASE_MAX : c_int = 36; + pub static _SC_BC_DIM_MAX : c_int = 37; + pub static _SC_BC_SCALE_MAX : c_int = 38; + pub static _SC_BC_STRING_MAX : c_int = 39; + pub static _SC_COLL_WEIGHTS_MAX : c_int = 40; + pub static _SC_EXPR_NEST_MAX : c_int = 42; + pub static _SC_LINE_MAX : c_int = 43; + pub static _SC_RE_DUP_MAX : c_int = 44; + pub static _SC_2_VERSION : c_int = 46; + pub static _SC_2_C_BIND : c_int = 47; + pub static _SC_2_C_DEV : c_int = 48; + pub static _SC_2_FORT_DEV : c_int = 49; + pub static _SC_2_FORT_RUN : c_int = 50; + pub static _SC_2_SW_DEV : c_int = 51; + pub static _SC_2_LOCALEDEF : c_int = 52; + pub static _SC_2_CHAR_TERM : c_int = 95; + pub static _SC_2_C_VERSION : c_int = 96; + pub static _SC_2_UPE : c_int = 97; + pub static _SC_XBS5_ILP32_OFF32 : c_int = 125; + pub static _SC_XBS5_ILP32_OFFBIG : c_int = 126; + pub static _SC_XBS5_LPBIG_OFFBIG : c_int = 128; } pub mod posix01 { - pub static SIGTRAP : int = 5; - - pub static GLOB_ERR : int = 1 << 0; - pub static GLOB_MARK : int = 1 << 1; - pub static GLOB_NOSORT : int = 1 << 2; - pub static GLOB_DOOFFS : int = 1 << 3; - pub static GLOB_NOCHECK : int = 1 << 4; - pub static GLOB_APPEND : int = 1 << 5; - pub static GLOB_NOESCAPE : int = 1 << 6; - - pub static GLOB_NOSPACE : int = 1; - pub static GLOB_ABORTED : int = 2; - pub static GLOB_NOMATCH : int = 3; + use libc::types::os::arch::c95::c_int; + + pub static SIGTRAP : c_int = 5; + + pub static GLOB_ERR : c_int = 1 << 0; + pub static GLOB_MARK : c_int = 1 << 1; + pub static GLOB_NOSORT : c_int = 1 << 2; + pub static GLOB_DOOFFS : c_int = 1 << 3; + pub static GLOB_NOCHECK : c_int = 1 << 4; + pub static GLOB_APPEND : c_int = 1 << 5; + pub static GLOB_NOESCAPE : c_int = 1 << 6; + + pub static GLOB_NOSPACE : c_int = 1; + pub static GLOB_ABORTED : c_int = 2; + pub static GLOB_NOMATCH : c_int = 3; + + pub static POSIX_MADV_NORMAL : c_int = 0; + pub static POSIX_MADV_RANDOM : c_int = 1; + pub static POSIX_MADV_SEQUENTIAL : c_int = 2; + pub static POSIX_MADV_WILLNEED : c_int = 3; + pub static POSIX_MADV_DONTNEED : c_int = 4; + + pub static _SC_MQ_PRIO_MAX : c_int = 28; + pub static _SC_IOV_MAX : c_int = 60; + pub static _SC_GETGR_R_SIZE_MAX : c_int = 69; + pub static _SC_GETPW_R_SIZE_MAX : c_int = 70; + pub static _SC_LOGIN_NAME_MAX : c_int = 71; + pub static _SC_TTY_NAME_MAX : c_int = 72; + pub static _SC_THREADS : c_int = 67; + pub static _SC_THREAD_SAFE_FUNCTIONS : c_int = 68; + pub static _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73; + pub static _SC_THREAD_KEYS_MAX : c_int = 74; + pub static _SC_THREAD_STACK_MIN : c_int = 75; + pub static _SC_THREAD_THREADS_MAX : c_int = 76; + pub static _SC_THREAD_ATTR_STACKADDR : c_int = 77; + pub static _SC_THREAD_ATTR_STACKSIZE : c_int = 78; + pub static _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79; + pub static _SC_THREAD_PRIO_INHERIT : c_int = 80; + pub static _SC_THREAD_PRIO_PROTECT : c_int = 81; + pub static _SC_THREAD_PROCESS_SHARED : c_int = 82; + pub static _SC_ATEXIT_MAX : c_int = 87; + pub static _SC_XOPEN_VERSION : c_int = 89; + pub static _SC_XOPEN_XCU_VERSION : c_int = 90; + pub static _SC_XOPEN_UNIX : c_int = 91; + pub static _SC_XOPEN_CRYPT : c_int = 92; + pub static _SC_XOPEN_ENH_I18N : c_int = 93; + pub static _SC_XOPEN_SHM : c_int = 94; + pub static _SC_XOPEN_LEGACY : c_int = 129; + pub static _SC_XOPEN_REALTIME : c_int = 130; + pub static _SC_XOPEN_REALTIME_THREADS : c_int = 131; } pub mod posix08 { } pub mod bsd44 { + use libc::types::os::arch::c95::c_int; + + pub static MADV_NORMAL : c_int = 0; + pub static MADV_RANDOM : c_int = 1; + pub static MADV_SEQUENTIAL : c_int = 2; + pub static MADV_WILLNEED : c_int = 3; + pub static MADV_DONTNEED : c_int = 4; + pub static MADV_REMOVE : c_int = 9; + pub static MADV_DONTFORK : c_int = 10; + pub static MADV_DOFORK : c_int = 11; + pub static MADV_MERGEABLE : c_int = 12; + pub static MADV_UNMERGEABLE : c_int = 13; + pub static MADV_HWPOISON : c_int = 100; } #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")] #[cfg(target_arch = "arm")] pub mod extra { - pub static O_RSYNC : int = 1052672; - pub static O_DSYNC : int = 4096; - pub static O_SYNC : int = 1052672; + use libc::types::os::arch::c95::c_int; + + pub static O_RSYNC : c_int = 1052672; + pub static O_DSYNC : c_int = 4096; + pub static O_SYNC : c_int = 1052672; + + pub static PROT_GROWSDOWN : c_int = 0x010000000; + pub static PROT_GROWSUP : c_int = 0x020000000; + + pub static MAP_TYPE : c_int = 0x000f; + pub static MAP_ANONONYMOUS : c_int = 0x1000; + pub static MAP_32BIT : c_int = 0x0040; + pub static MAP_GROWSDOWN : c_int = 0x0100; + pub static MAP_DENYWRITE : c_int = 0x0800; + pub static MAP_EXECUTABLE : c_int = 0x01000; + pub static MAP_LOCKED : c_int = 0x02000; + pub static MAP_NONRESERVE : c_int = 0x04000; + pub static MAP_POPULATE : c_int = 0x08000; + pub static MAP_NONBLOCK : c_int = 0x010000; + pub static MAP_STACK : c_int = 0x020000; } #[cfg(target_arch = "mips")] pub mod extra { - pub static O_RSYNC : int = 16400; - pub static O_DSYNC : int = 16; - pub static O_SYNC : int = 16400; + use libc::types::os::arch::c95::c_int; + + pub static O_RSYNC : c_int = 16400; + pub static O_DSYNC : c_int = 16; + pub static O_SYNC : c_int = 16400; + + pub static PROT_GROWSDOWN : c_int = 0x010000000; + pub static PROT_GROWSUP : c_int = 0x020000000; + + pub static MAP_TYPE : c_int = 0x000f; + pub static MAP_ANONONYMOUS : c_int = 0x1000; + pub static MAP_32BIT : c_int = 0x0040; + pub static MAP_GROWSDOWN : c_int = 0x0100; + pub static MAP_DENYWRITE : c_int = 0x0800; + pub static MAP_EXECUTABLE : c_int = 0x01000; + pub static MAP_LOCKED : c_int = 0x02000; + pub static MAP_NONRESERVE : c_int = 0x04000; + pub static MAP_POPULATE : c_int = 0x08000; + pub static MAP_NONBLOCK : c_int = 0x010000; + pub static MAP_STACK : c_int = 0x020000; } } #[cfg(target_os = "freebsd")] pub mod os { pub mod c95 { - pub static EXIT_FAILURE : int = 1; - pub static EXIT_SUCCESS : int = 0; - pub static RAND_MAX : int = 2147483647; - pub static EOF : int = -1; - pub static SEEK_SET : int = 0; - pub static SEEK_CUR : int = 1; - pub static SEEK_END : int = 2; - pub static _IOFBF : int = 0; - pub static _IONBF : int = 2; - pub static _IOLBF : int = 1; - pub static BUFSIZ : uint = 1024_u; - pub static FOPEN_MAX : uint = 20_u; - pub static FILENAME_MAX : uint = 1024_u; - pub static L_tmpnam : uint = 1024_u; - pub static TMP_MAX : uint = 308915776_u; + use libc::types::os::arch::c95::{c_int, c_uint}; + + pub static EXIT_FAILURE : c_int = 1; + pub static EXIT_SUCCESS : c_int = 0; + pub static RAND_MAX : c_int = 2147483647; + pub static EOF : c_int = -1; + pub static SEEK_SET : c_int = 0; + pub static SEEK_CUR : c_int = 1; + pub static SEEK_END : c_int = 2; + pub static _IOFBF : c_int = 0; + pub static _IONBF : c_int = 2; + pub static _IOLBF : c_int = 1; + pub static BUFSIZ : c_uint = 1024_u32; + pub static FOPEN_MAX : c_uint = 20_u32; + pub static FILENAME_MAX : c_uint = 1024_u32; + pub static L_tmpnam : c_uint = 1024_u32; + pub static TMP_MAX : c_uint = 308915776_u32; } pub mod c99 { } pub mod posix88 { - pub static O_RDONLY : int = 0; - pub static O_WRONLY : int = 1; - pub static O_RDWR : int = 2; - pub static O_APPEND : int = 8; - pub static O_CREAT : int = 512; - pub static O_EXCL : int = 2048; - pub static O_TRUNC : int = 1024; - pub static S_IFIFO : int = 4096; - pub static S_IFCHR : int = 8192; - pub static S_IFBLK : int = 24576; - pub static S_IFDIR : int = 16384; - pub static S_IFREG : int = 32768; - pub static S_IFMT : int = 61440; - pub static S_IEXEC : int = 64; - pub static S_IWRITE : int = 128; - pub static S_IREAD : int = 256; - pub static S_IRWXU : int = 448; - pub static S_IXUSR : int = 64; - pub static S_IWUSR : int = 128; - pub static S_IRUSR : int = 256; - pub static F_OK : int = 0; - pub static R_OK : int = 4; - pub static W_OK : int = 2; - pub static X_OK : int = 1; - pub static STDIN_FILENO : int = 0; - pub static STDOUT_FILENO : int = 1; - pub static STDERR_FILENO : int = 2; - pub static F_LOCK : int = 1; - pub static F_TEST : int = 3; - pub static F_TLOCK : int = 2; - pub static F_ULOCK : int = 0; - pub static SIGHUP : int = 1; - pub static SIGINT : int = 2; - pub static SIGQUIT : int = 3; - pub static SIGILL : int = 4; - pub static SIGABRT : int = 6; - pub static SIGFPE : int = 8; - pub static SIGKILL : int = 9; - pub static SIGSEGV : int = 11; - pub static SIGPIPE : int = 13; - pub static SIGALRM : int = 14; - pub static SIGTERM : int = 15; + use libc::types::common::c95::c_void; + use libc::types::os::arch::c95::c_int; + + pub static O_RDONLY : c_int = 0; + pub static O_WRONLY : c_int = 1; + pub static O_RDWR : c_int = 2; + pub static O_APPEND : c_int = 8; + pub static O_CREAT : c_int = 512; + pub static O_EXCL : c_int = 2048; + pub static O_TRUNC : c_int = 1024; + pub static S_IFIFO : c_int = 4096; + pub static S_IFCHR : c_int = 8192; + pub static S_IFBLK : c_int = 24576; + pub static S_IFDIR : c_int = 16384; + pub static S_IFREG : c_int = 32768; + pub static S_IFMT : c_int = 61440; + pub static S_IEXEC : c_int = 64; + pub static S_IWRITE : c_int = 128; + pub static S_IREAD : c_int = 256; + pub static S_IRWXU : c_int = 448; + pub static S_IXUSR : c_int = 64; + pub static S_IWUSR : c_int = 128; + pub static S_IRUSR : c_int = 256; + pub static F_OK : c_int = 0; + pub static R_OK : c_int = 4; + pub static W_OK : c_int = 2; + pub static X_OK : c_int = 1; + pub static STDIN_FILENO : c_int = 0; + pub static STDOUT_FILENO : c_int = 1; + pub static STDERR_FILENO : c_int = 2; + pub static F_LOCK : c_int = 1; + pub static F_TEST : c_int = 3; + pub static F_TLOCK : c_int = 2; + pub static F_ULOCK : c_int = 0; + pub static SIGHUP : c_int = 1; + pub static SIGINT : c_int = 2; + pub static SIGQUIT : c_int = 3; + pub static SIGILL : c_int = 4; + pub static SIGABRT : c_int = 6; + pub static SIGFPE : c_int = 8; + pub static SIGKILL : c_int = 9; + pub static SIGSEGV : c_int = 11; + pub static SIGPIPE : c_int = 13; + pub static SIGALRM : c_int = 14; + pub static SIGTERM : c_int = 15; + + pub static PROT_NONE : c_int = 0; + pub static PROT_READ : c_int = 1; + pub static PROT_WRITE : c_int = 2; + pub static PROT_EXEC : c_int = 4; + + pub static MAP_FILE : c_int = 0x0000; + pub static MAP_SHARED : c_int = 0x0001; + pub static MAP_PRIVATE : c_int = 0x0002; + pub static MAP_FIXED : c_int = 0x0010; + pub static MAP_ANON : c_int = 0x1000; + + pub static MAP_FAILED : *c_void = -1 as *c_void; + + pub static MCL_CURRENT : c_int = 0x0001; + pub static MCL_FUTURE : c_int = 0x0002; + + pub static MS_SYNC : c_int = 0x0000; + pub static MS_ASYNC : c_int = 0x0001; + pub static MS_INVALIDATE : c_int = 0x0002; + + pub static _SC_ARG_MAX : c_int = 1; + pub static _SC_CHILD_MAX : c_int = 2; + pub static _SC_CLK_TCK : c_int = 3; + pub static _SC_NGROUPS_MAX : c_int = 4; + pub static _SC_OPEN_MAX : c_int = 5; + pub static _SC_JOB_CONTROL : c_int = 6; + pub static _SC_SAVED_IDS : c_int = 7; + pub static _SC_VERSION : c_int = 8; + pub static _SC_BC_BASE_MAX : c_int = 9; + pub static _SC_BC_DIM_MAX : c_int = 10; + pub static _SC_BC_SCALE_MAX : c_int = 11; + pub static _SC_BC_STRING_MAX : c_int = 12; + pub static _SC_COLL_WEIGHTS_MAX : c_int = 13; + pub static _SC_EXPR_NEST_MAX : c_int = 14; + pub static _SC_LINE_MAX : c_int = 15; + pub static _SC_RE_DUP_MAX : c_int = 16; + pub static _SC_2_VERSION : c_int = 17; + pub static _SC_2_C_BIND : c_int = 18; + pub static _SC_2_C_DEV : c_int = 19; + pub static _SC_2_CHAR_TERM : c_int = 20; + pub static _SC_2_FORT_DEV : c_int = 21; + pub static _SC_2_FORT_RUN : c_int = 22; + pub static _SC_2_LOCALEDEF : c_int = 23; + pub static _SC_2_SW_DEV : c_int = 24; + pub static _SC_2_UPE : c_int = 25; + pub static _SC_STREAM_MAX : c_int = 26; + pub static _SC_TZNAME_MAX : c_int = 27; + pub static _SC_ASYNCHRONOUS_IO : c_int = 28; + pub static _SC_MAPPED_FILES : c_int = 29; + pub static _SC_MEMLOCK : c_int = 30; + pub static _SC_MEMLOCK_RANGE : c_int = 31; + pub static _SC_MEMORY_PROTECTION : c_int = 32; + pub static _SC_MESSAGE_PASSING : c_int = 33; + pub static _SC_PRIORITIZED_IO : c_int = 34; + pub static _SC_PRIORITY_SCHEDULING : c_int = 35; + pub static _SC_REALTIME_SIGNALS : c_int = 36; + pub static _SC_SEMAPHORES : c_int = 37; + pub static _SC_FSYNC : c_int = 38; + pub static _SC_SHARED_MEMORY_OBJECTS : c_int = 39; + pub static _SC_SYNCHRONIZED_IO : c_int = 40; + pub static _SC_TIMERS : c_int = 41; + pub static _SC_AIO_LISTIO_MAX : c_int = 42; + pub static _SC_AIO_MAX : c_int = 43; + pub static _SC_AIO_PRIO_DELTA_MAX : c_int = 44; + pub static _SC_DELAYTIMER_MAX : c_int = 45; + pub static _SC_MQ_OPEN_MAX : c_int = 46; + pub static _SC_PAGESIZE : c_int = 47; + pub static _SC_RTSIG_MAX : c_int = 48; + pub static _SC_SEM_NSEMS_MAX : c_int = 49; + pub static _SC_SEM_VALUE_MAX : c_int = 50; + pub static _SC_SIGQUEUE_MAX : c_int = 51; + pub static _SC_TIMER_MAX : c_int = 52; } pub mod posix01 { - pub static SIGTRAP : int = 5; - - pub static GLOB_APPEND : int = 0x0001; - pub static GLOB_DOOFFS : int = 0x0002; - pub static GLOB_ERR : int = 0x0004; - pub static GLOB_MARK : int = 0x0008; - pub static GLOB_NOCHECK : int = 0x0010; - pub static GLOB_NOSORT : int = 0x0020; - pub static GLOB_NOESCAPE : int = 0x2000; - - pub static GLOB_NOSPACE : int = -1; - pub static GLOB_ABORTED : int = -2; - pub static GLOB_NOMATCH : int = -3; + use libc::types::os::arch::c95::c_int; + + pub static SIGTRAP : c_int = 5; + + pub static GLOB_APPEND : c_int = 0x0001; + pub static GLOB_DOOFFS : c_int = 0x0002; + pub static GLOB_ERR : c_int = 0x0004; + pub static GLOB_MARK : c_int = 0x0008; + pub static GLOB_NOCHECK : c_int = 0x0010; + pub static GLOB_NOSORT : c_int = 0x0020; + pub static GLOB_NOESCAPE : c_int = 0x2000; + + pub static GLOB_NOSPACE : c_int = -1; + pub static GLOB_ABORTED : c_int = -2; + pub static GLOB_NOMATCH : c_int = -3; + + pub static POSIX_MADV_NORMAL : c_int = 0; + pub static POSIX_MADV_RANDOM : c_int = 1; + pub static POSIX_MADV_SEQUENTIAL : c_int = 2; + pub static POSIX_MADV_WILLNEED : c_int = 3; + pub static POSIX_MADV_DONTNEED : c_int = 4; + + pub static _SC_IOV_MAX : c_int = 56; + pub static _SC_GETGR_R_SIZE_MAX : c_int = 70; + pub static _SC_GETPW_R_SIZE_MAX : c_int = 71; + pub static _SC_LOGIN_NAME_MAX : c_int = 73; + pub static _SC_MQ_PRIO_MAX : c_int = 75; + pub static _SC_THREAD_ATTR_STACKADDR : c_int = 82; + pub static _SC_THREAD_ATTR_STACKSIZE : c_int = 83; + pub static _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 85; + pub static _SC_THREAD_KEYS_MAX : c_int = 86; + pub static _SC_THREAD_PRIO_INHERIT : c_int = 87; + pub static _SC_THREAD_PRIO_PROTECT : c_int = 88; + pub static _SC_THREAD_PRIORITY_SCHEDULING : c_int = 89; + pub static _SC_THREAD_PROCESS_SHARED : c_int = 90; + pub static _SC_THREAD_SAFE_FUNCTIONS : c_int = 91; + pub static _SC_THREAD_STACK_MIN : c_int = 93; + pub static _SC_THREAD_THREADS_MAX : c_int = 94; + pub static _SC_THREADS : c_int = 96; + pub static _SC_TTY_NAME_MAX : c_int = 101; + pub static _SC_ATEXIT_MAX : c_int = 107; + pub static _SC_XOPEN_CRYPT : c_int = 108; + pub static _SC_XOPEN_ENH_I18N : c_int = 109; + pub static _SC_XOPEN_LEGACY : c_int = 110; + pub static _SC_XOPEN_REALTIME : c_int = 111; + pub static _SC_XOPEN_REALTIME_THREADS : c_int = 112; + pub static _SC_XOPEN_SHM : c_int = 113; + pub static _SC_XOPEN_UNIX : c_int = 115; + pub static _SC_XOPEN_VERSION : c_int = 116; + pub static _SC_XOPEN_XCU_VERSION : c_int = 117; } pub mod posix08 { } pub mod bsd44 { + use libc::types::os::arch::c95::c_int; + + pub static MADV_NORMAL : c_int = 0; + pub static MADV_RANDOM : c_int = 1; + pub static MADV_SEQUENTIAL : c_int = 2; + pub static MADV_WILLNEED : c_int = 3; + pub static MADV_DONTNEED : c_int = 4; + pub static MADV_FREE : c_int = 5; + pub static MADV_NOSYNC : c_int = 6; + pub static MADV_AUTOSYNC : c_int = 7; + pub static MADV_NOCORE : c_int = 8; + pub static MADV_CORE : c_int = 9; + pub static MADV_PROTECT : c_int = 10; + + pub static MINCORE_INCORE : c_int = 0x1; + pub static MINCORE_REFERENCED : c_int = 0x2; + pub static MINCORE_MODIFIED : c_int = 0x4; + pub static MINCORE_REFERENCED_OTHER : c_int = 0x8; + pub static MINCORE_MODIFIED_OTHER : c_int = 0x10; + pub static MINCORE_SUPER : c_int = 0x20; } pub mod extra { - pub static O_SYNC : int = 128; - pub static CTL_KERN: int = 1; - pub static KERN_PROC: int = 14; - pub static KERN_PROC_PATHNAME: int = 12; + use libc::types::os::arch::c95::c_int; + + pub static O_SYNC : c_int = 128; + pub static CTL_KERN: c_int = 1; + pub static KERN_PROC: c_int = 14; + pub static KERN_PROC_PATHNAME: c_int = 12; + + pub static MAP_COPY : c_int = 0x0002; + pub static MAP_RENAME : c_int = 0x0020; + pub static MAP_NORESERVE : c_int = 0x0040; + pub static MAP_HASSEMAPHORE : c_int = 0x0200; + pub static MAP_STACK : c_int = 0x0400; + pub static MAP_NOSYNC : c_int = 0x0800; + pub static MAP_NOCORE : c_int = 0x020000; } } #[cfg(target_os = "macos")] pub mod os { pub mod c95 { - pub static EXIT_FAILURE : int = 1; - pub static EXIT_SUCCESS : int = 0; - pub static RAND_MAX : int = 2147483647; - pub static EOF : int = -1; - pub static SEEK_SET : int = 0; - pub static SEEK_CUR : int = 1; - pub static SEEK_END : int = 2; - pub static _IOFBF : int = 0; - pub static _IONBF : int = 2; - pub static _IOLBF : int = 1; - pub static BUFSIZ : uint = 1024_u; - pub static FOPEN_MAX : uint = 20_u; - pub static FILENAME_MAX : uint = 1024_u; - pub static L_tmpnam : uint = 1024_u; - pub static TMP_MAX : uint = 308915776_u; + use libc::types::os::arch::c95::{c_int, c_uint}; + + pub static EXIT_FAILURE : c_int = 1; + pub static EXIT_SUCCESS : c_int = 0; + pub static RAND_MAX : c_int = 2147483647; + pub static EOF : c_int = -1; + pub static SEEK_SET : c_int = 0; + pub static SEEK_CUR : c_int = 1; + pub static SEEK_END : c_int = 2; + pub static _IOFBF : c_int = 0; + pub static _IONBF : c_int = 2; + pub static _IOLBF : c_int = 1; + pub static BUFSIZ : c_uint = 1024_u32; + pub static FOPEN_MAX : c_uint = 20_u32; + pub static FILENAME_MAX : c_uint = 1024_u32; + pub static L_tmpnam : c_uint = 1024_u32; + pub static TMP_MAX : c_uint = 308915776_u32; } pub mod c99 { } pub mod posix88 { - pub static O_RDONLY : int = 0; - pub static O_WRONLY : int = 1; - pub static O_RDWR : int = 2; - pub static O_APPEND : int = 8; - pub static O_CREAT : int = 512; - pub static O_EXCL : int = 2048; - pub static O_TRUNC : int = 1024; - pub static S_IFIFO : int = 4096; - pub static S_IFCHR : int = 8192; - pub static S_IFBLK : int = 24576; - pub static S_IFDIR : int = 16384; - pub static S_IFREG : int = 32768; - pub static S_IFMT : int = 61440; - pub static S_IEXEC : int = 64; - pub static S_IWRITE : int = 128; - pub static S_IREAD : int = 256; - pub static S_IRWXU : int = 448; - pub static S_IXUSR : int = 64; - pub static S_IWUSR : int = 128; - pub static S_IRUSR : int = 256; - pub static F_OK : int = 0; - pub static R_OK : int = 4; - pub static W_OK : int = 2; - pub static X_OK : int = 1; - pub static STDIN_FILENO : int = 0; - pub static STDOUT_FILENO : int = 1; - pub static STDERR_FILENO : int = 2; - pub static F_LOCK : int = 1; - pub static F_TEST : int = 3; - pub static F_TLOCK : int = 2; - pub static F_ULOCK : int = 0; - pub static SIGHUP : int = 1; - pub static SIGINT : int = 2; - pub static SIGQUIT : int = 3; - pub static SIGILL : int = 4; - pub static SIGABRT : int = 6; - pub static SIGFPE : int = 8; - pub static SIGKILL : int = 9; - pub static SIGSEGV : int = 11; - pub static SIGPIPE : int = 13; - pub static SIGALRM : int = 14; - pub static SIGTERM : int = 15; + use libc::types::common::c95::c_void; + use libc::types::os::arch::c95::c_int; + + pub static O_RDONLY : c_int = 0; + pub static O_WRONLY : c_int = 1; + pub static O_RDWR : c_int = 2; + pub static O_APPEND : c_int = 8; + pub static O_CREAT : c_int = 512; + pub static O_EXCL : c_int = 2048; + pub static O_TRUNC : c_int = 1024; + pub static S_IFIFO : c_int = 4096; + pub static S_IFCHR : c_int = 8192; + pub static S_IFBLK : c_int = 24576; + pub static S_IFDIR : c_int = 16384; + pub static S_IFREG : c_int = 32768; + pub static S_IFMT : c_int = 61440; + pub static S_IEXEC : c_int = 64; + pub static S_IWRITE : c_int = 128; + pub static S_IREAD : c_int = 256; + pub static S_IRWXU : c_int = 448; + pub static S_IXUSR : c_int = 64; + pub static S_IWUSR : c_int = 128; + pub static S_IRUSR : c_int = 256; + pub static F_OK : c_int = 0; + pub static R_OK : c_int = 4; + pub static W_OK : c_int = 2; + pub static X_OK : c_int = 1; + pub static STDIN_FILENO : c_int = 0; + pub static STDOUT_FILENO : c_int = 1; + pub static STDERR_FILENO : c_int = 2; + pub static F_LOCK : c_int = 1; + pub static F_TEST : c_int = 3; + pub static F_TLOCK : c_int = 2; + pub static F_ULOCK : c_int = 0; + pub static SIGHUP : c_int = 1; + pub static SIGINT : c_int = 2; + pub static SIGQUIT : c_int = 3; + pub static SIGILL : c_int = 4; + pub static SIGABRT : c_int = 6; + pub static SIGFPE : c_int = 8; + pub static SIGKILL : c_int = 9; + pub static SIGSEGV : c_int = 11; + pub static SIGPIPE : c_int = 13; + pub static SIGALRM : c_int = 14; + pub static SIGTERM : c_int = 15; + + pub static PROT_NONE : c_int = 0; + pub static PROT_READ : c_int = 1; + pub static PROT_WRITE : c_int = 2; + pub static PROT_EXEC : c_int = 4; + + pub static MAP_FILE : c_int = 0x0000; + pub static MAP_SHARED : c_int = 0x0001; + pub static MAP_PRIVATE : c_int = 0x0002; + pub static MAP_FIXED : c_int = 0x0010; + pub static MAP_ANON : c_int = 0x1000; + + pub static MAP_FAILED : *c_void = -1 as *c_void; + + pub static MCL_CURRENT : c_int = 0x0001; + pub static MCL_FUTURE : c_int = 0x0002; + + pub static MS_ASYNC : c_int = 0x0001; + pub static MS_INVALIDATE : c_int = 0x0002; + pub static MS_SYNC : c_int = 0x0010; + + pub static MS_KILLPAGES : c_int = 0x0004; + pub static MS_DEACTIVATE : c_int = 0x0008; + + pub static _SC_ARG_MAX : c_int = 1; + pub static _SC_CHILD_MAX : c_int = 2; + pub static _SC_CLK_TCK : c_int = 3; + pub static _SC_NGROUPS_MAX : c_int = 4; + pub static _SC_OPEN_MAX : c_int = 5; + pub static _SC_JOB_CONTROL : c_int = 6; + pub static _SC_SAVED_IDS : c_int = 7; + pub static _SC_VERSION : c_int = 8; + pub static _SC_BC_BASE_MAX : c_int = 9; + pub static _SC_BC_DIM_MAX : c_int = 10; + pub static _SC_BC_SCALE_MAX : c_int = 11; + pub static _SC_BC_STRING_MAX : c_int = 12; + pub static _SC_COLL_WEIGHTS_MAX : c_int = 13; + pub static _SC_EXPR_NEST_MAX : c_int = 14; + pub static _SC_LINE_MAX : c_int = 15; + pub static _SC_RE_DUP_MAX : c_int = 16; + pub static _SC_2_VERSION : c_int = 17; + pub static _SC_2_C_BIND : c_int = 18; + pub static _SC_2_C_DEV : c_int = 19; + pub static _SC_2_CHAR_TERM : c_int = 20; + pub static _SC_2_FORT_DEV : c_int = 21; + pub static _SC_2_FORT_RUN : c_int = 22; + pub static _SC_2_LOCALEDEF : c_int = 23; + pub static _SC_2_SW_DEV : c_int = 24; + pub static _SC_2_UPE : c_int = 25; + pub static _SC_STREAM_MAX : c_int = 26; + pub static _SC_TZNAME_MAX : c_int = 27; + pub static _SC_ASYNCHRONOUS_IO : c_int = 28; + pub static _SC_PAGESIZE : c_int = 29; + pub static _SC_MEMLOCK : c_int = 30; + pub static _SC_MEMLOCK_RANGE : c_int = 31; + pub static _SC_MEMORY_PROTECTION : c_int = 32; + pub static _SC_MESSAGE_PASSING : c_int = 33; + pub static _SC_PRIORITIZED_IO : c_int = 34; + pub static _SC_PRIORITY_SCHEDULING : c_int = 35; + pub static _SC_REALTIME_SIGNALS : c_int = 36; + pub static _SC_SEMAPHORES : c_int = 37; + pub static _SC_FSYNC : c_int = 38; + pub static _SC_SHARED_MEMORY_OBJECTS : c_int = 39; + pub static _SC_SYNCHRONIZED_IO : c_int = 40; + pub static _SC_TIMERS : c_int = 41; + pub static _SC_AIO_LISTIO_MAX : c_int = 42; + pub static _SC_AIO_MAX : c_int = 43; + pub static _SC_AIO_PRIO_DELTA_MAX : c_int = 44; + pub static _SC_DELAYTIMER_MAX : c_int = 45; + pub static _SC_MQ_OPEN_MAX : c_int = 46; + pub static _SC_MAPPED_FILES : c_int = 47; + pub static _SC_RTSIG_MAX : c_int = 48; + pub static _SC_SEM_NSEMS_MAX : c_int = 49; + pub static _SC_SEM_VALUE_MAX : c_int = 50; + pub static _SC_SIGQUEUE_MAX : c_int = 51; + pub static _SC_TIMER_MAX : c_int = 52; + pub static _SC_XBS5_ILP32_OFF32 : c_int = 122; + pub static _SC_XBS5_ILP32_OFFBIG : c_int = 123; + pub static _SC_XBS5_LP64_OFF64 : c_int = 124; + pub static _SC_XBS5_LPBIG_OFFBIG : c_int = 125; } pub mod posix01 { - pub static SIGTRAP : int = 5; - - pub static GLOB_APPEND : int = 0x0001; - pub static GLOB_DOOFFS : int = 0x0002; - pub static GLOB_ERR : int = 0x0004; - pub static GLOB_MARK : int = 0x0008; - pub static GLOB_NOCHECK : int = 0x0010; - pub static GLOB_NOSORT : int = 0x0020; - pub static GLOB_NOESCAPE : int = 0x2000; - - pub static GLOB_NOSPACE : int = -1; - pub static GLOB_ABORTED : int = -2; - pub static GLOB_NOMATCH : int = -3; + use libc::types::os::arch::c95::c_int; + + pub static SIGTRAP : c_int = 5; + + pub static GLOB_APPEND : c_int = 0x0001; + pub static GLOB_DOOFFS : c_int = 0x0002; + pub static GLOB_ERR : c_int = 0x0004; + pub static GLOB_MARK : c_int = 0x0008; + pub static GLOB_NOCHECK : c_int = 0x0010; + pub static GLOB_NOSORT : c_int = 0x0020; + pub static GLOB_NOESCAPE : c_int = 0x2000; + + pub static GLOB_NOSPACE : c_int = -1; + pub static GLOB_ABORTED : c_int = -2; + pub static GLOB_NOMATCH : c_int = -3; + + pub static POSIX_MADV_NORMAL : c_int = 0; + pub static POSIX_MADV_RANDOM : c_int = 1; + pub static POSIX_MADV_SEQUENTIAL : c_int = 2; + pub static POSIX_MADV_WILLNEED : c_int = 3; + pub static POSIX_MADV_DONTNEED : c_int = 4; + + pub static _SC_IOV_MAX : c_int = 56; + pub static _SC_GETGR_R_SIZE_MAX : c_int = 70; + pub static _SC_GETPW_R_SIZE_MAX : c_int = 71; + pub static _SC_LOGIN_NAME_MAX : c_int = 73; + pub static _SC_MQ_PRIO_MAX : c_int = 75; + pub static _SC_THREAD_ATTR_STACKADDR : c_int = 82; + pub static _SC_THREAD_ATTR_STACKSIZE : c_int = 83; + pub static _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 85; + pub static _SC_THREAD_KEYS_MAX : c_int = 86; + pub static _SC_THREAD_PRIO_INHERIT : c_int = 87; + pub static _SC_THREAD_PRIO_PROTECT : c_int = 88; + pub static _SC_THREAD_PRIORITY_SCHEDULING : c_int = 89; + pub static _SC_THREAD_PROCESS_SHARED : c_int = 90; + pub static _SC_THREAD_SAFE_FUNCTIONS : c_int = 91; + pub static _SC_THREAD_STACK_MIN : c_int = 93; + pub static _SC_THREAD_THREADS_MAX : c_int = 94; + pub static _SC_THREADS : c_int = 96; + pub static _SC_TTY_NAME_MAX : c_int = 101; + pub static _SC_ATEXIT_MAX : c_int = 107; + pub static _SC_XOPEN_CRYPT : c_int = 108; + pub static _SC_XOPEN_ENH_I18N : c_int = 109; + pub static _SC_XOPEN_LEGACY : c_int = 110; + pub static _SC_XOPEN_REALTIME : c_int = 111; + pub static _SC_XOPEN_REALTIME_THREADS : c_int = 112; + pub static _SC_XOPEN_SHM : c_int = 113; + pub static _SC_XOPEN_UNIX : c_int = 115; + pub static _SC_XOPEN_VERSION : c_int = 116; + pub static _SC_XOPEN_XCU_VERSION : c_int = 121; } pub mod posix08 { } pub mod bsd44 { + use libc::types::os::arch::c95::c_int; + + pub static MADV_NORMAL : c_int = 0; + pub static MADV_RANDOM : c_int = 1; + pub static MADV_SEQUENTIAL : c_int = 2; + pub static MADV_WILLNEED : c_int = 3; + pub static MADV_DONTNEED : c_int = 4; + pub static MADV_FREE : c_int = 5; + pub static MADV_ZERO_WIRED_PAGES : c_int = 6; + pub static MADV_FREE_REUSABLE : c_int = 7; + pub static MADV_FREE_REUSE : c_int = 8; + pub static MADV_CAN_REUSE : c_int = 9; + + pub static MINCORE_INCORE : c_int = 0x1; + pub static MINCORE_REFERENCED : c_int = 0x2; + pub static MINCORE_MODIFIED : c_int = 0x4; + pub static MINCORE_REFERENCED_OTHER : c_int = 0x8; + pub static MINCORE_MODIFIED_OTHER : c_int = 0x10; } pub mod extra { - pub static O_DSYNC : int = 4194304; - pub static O_SYNC : int = 128; - pub static F_FULLFSYNC : int = 51; + use libc::types::os::arch::c95::c_int; + + pub static O_DSYNC : c_int = 4194304; + pub static O_SYNC : c_int = 128; + pub static F_FULLFSYNC : c_int = 51; + + pub static MAP_COPY : c_int = 0x0002; + pub static MAP_RENAME : c_int = 0x0020; + pub static MAP_NORESERVE : c_int = 0x0040; + pub static MAP_NOEXTEND : c_int = 0x0100; + pub static MAP_HASSEMAPHORE : c_int = 0x0200; + pub static MAP_NOCACHE : c_int = 0x0400; + pub static MAP_JIT : c_int = 0x0800; } } } @@ -1407,7 +1945,7 @@ pub mod funcs { #[fast_ffi] unsafe fn malloc(size: size_t) -> *c_void; #[fast_ffi] - unsafe fn realloc(p: *c_void, size: size_t) -> *c_void; + unsafe fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; #[fast_ffi] unsafe fn free(p: *c_void); unsafe fn abort() -> !; @@ -1610,6 +2148,9 @@ pub mod funcs { -> c_int; } } + + pub mod mman { + } } @@ -1787,6 +2328,38 @@ pub mod funcs { unsafe fn kill(pid: pid_t, sig: c_int) -> c_int; } } + + #[nolink] + #[abi = "cdecl"] + pub mod mman { + use libc::types::common::c95::{c_void}; + use libc::types::os::arch::c95::{size_t, c_int, c_char}; + use libc::types::os::arch::posix88::{mode_t, off_t}; + + pub extern { + unsafe fn mlock(addr: *c_void, len: size_t) -> c_int; + unsafe fn munlock(addr: *c_void, len: size_t) -> c_int; + unsafe fn mlockall(flags: c_int) -> c_int; + unsafe fn munlockall() -> c_int; + + unsafe fn mmap(addr: *c_void, + len: size_t, + prot: c_int, + flags: c_int, + fd: c_int, + offset: off_t) -> *mut c_void; + unsafe fn munmap(addr: *c_void, len: size_t) -> c_int; + + unsafe fn mprotect(addr: *c_void, len: size_t, prot: c_int) + -> c_int; + + unsafe fn msync(addr: *c_void, len: size_t, flags: c_int) + -> c_int; + unsafe fn shm_open(name: *c_char, oflag: c_int, mode: mode_t) + -> c_int; + unsafe fn shm_unlink(name: *c_char) -> c_int; + } + } } #[cfg(target_os = "linux")] @@ -1865,6 +2438,19 @@ pub mod funcs { unsafe fn globfree(pglob: *mut glob_t); } } + + #[nolink] + #[abi = "cdecl"] + pub mod mman { + use libc::types::common::c95::{c_void}; + use libc::types::os::arch::c95::{c_int, size_t}; + + pub extern { + unsafe fn posix_madvise(addr: *c_void, + len: size_t, + advice: c_int) -> c_int; + } + } } #[cfg(target_os = "win32")] @@ -1877,6 +2463,9 @@ pub mod funcs { pub mod glob { } + + pub mod mman { + } } @@ -1895,7 +2484,8 @@ pub mod funcs { #[cfg(target_os = "freebsd")] pub mod bsd44 { use libc::types::common::c95::{c_void}; - use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t}; + use libc::types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, + size_t}; #[abi = "cdecl"] pub extern { @@ -1911,6 +2501,12 @@ pub mod funcs { sizep: *mut size_t) -> c_int; unsafe fn getdtablesize() -> c_int; + + unsafe fn madvise(addr: *c_void, len: size_t, advice: c_int) + -> c_int; + + unsafe fn mincore(addr: *c_void, len: size_t, vec: *c_uchar) + -> c_int; } } @@ -1918,11 +2514,18 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] pub mod bsd44 { - use libc::types::os::arch::c95::{c_int}; + use libc::types::common::c95::{c_void}; + use libc::types::os::arch::c95::{c_uchar, c_int, size_t}; #[abi = "cdecl"] pub extern { unsafe fn getdtablesize() -> c_int; + + unsafe fn madvise(addr: *c_void, len: size_t, advice: c_int) + -> c_int; + + unsafe fn mincore(addr: *c_void, len: size_t, vec: *c_uchar) + -> c_int; } } diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs index 82c01c998cf..c5f2c8ae584 100644 --- a/src/libstd/local_data.rs +++ b/src/libstd/local_data.rs @@ -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); diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs index d514612b5af..2c9fcb2999f 100644 --- a/src/libstd/managed.rs +++ b/src/libstd/managed.rs @@ -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; diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 117a474ffd7..0b6eb766b29 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -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 } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index e13dff1e623..c39c7a3a57d 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -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 } diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index c583aeacf16..7a6e3042e7b 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -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 } diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 74ec46ccfcd..f152d60cb7a 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -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 { diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index 30a18a0587b..b856c3c65ea 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -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 diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index a062838aacf..f6dff4267b7 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -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() } } )) @@ -146,6 +109,87 @@ static negative_inf_buf: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' 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 * conversion functions like `to_str()` or `to_str_radix()`. @@ -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) } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 52f620f97ce..25e338fcd0f 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -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 { diff --git a/src/libstd/old_iter.rs b/src/libstd/old_iter.rs deleted file mode 100644 index 83bb9eb0908..00000000000 --- a/src/libstd/old_iter.rs +++ /dev/null @@ -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); } - } -} diff --git a/src/libstd/ops.rs b/src/libstd/ops.rs index 77cfe62e495..020131ab119 100644 --- a/src/libstd/ops.rs +++ b/src/libstd/ops.rs @@ -14,7 +14,7 @@ #[lang="drop"] pub trait Drop { - fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton + fn drop(&self); } #[lang="add"] diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 7dc6b7fe4b1..64381231258 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -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()); +} diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 765dd30febc..20c4346d618 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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 } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 9c51526aa7f..a5e82c31d79 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -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,12 +349,35 @@ impl Path { } } - #[cfg(unix)] - pub fn lstat(&self) -> Option<libc::stat> { + 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), + } + } +} + +#[cfg(not(target_os = "win32"))] +impl PosixPath { + pub fn stat(&self) -> Option<libc::stat> { unsafe { - do str::as_c_str(self.to_str()) |buf| { + do str::as_c_str(self.to_str()) |buf| { let mut st = stat::arch::default_stat(); - match libc::lstat(buf, &mut st) { + match libc::stat(buf, &mut st) { 0 => Some(st), _ => None, } @@ -355,12 +405,21 @@ impl Path { 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 { diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 26dd4af45d6..49713a3a23b 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -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>]) { diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 309df27e151..d560ce621ea 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -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 diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 7f89d454be1..473f56ddd79 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -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)) } diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 739e3dfedc7..5f96e38a55a 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -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)] diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index 6f4f1a34977..e8dad2fc5e8 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -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 { diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index d276abf0c8b..16ab4771d0d 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -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; diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index ab3f83d34d5..fdda65d3e95 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -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 { - fn write_repr(&self, writer: @Writer) { - writer.write_uint(*self as uint); - } -} -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. +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 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) diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 6cef5c33de0..0b099b66ecf 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -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) diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 7608bc89e02..fba61711297 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -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() diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index e89df2b1c93..4b475d74397 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -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(); +extern { + #[rust_stack] + fn abort(); +} - inc_count(); +#[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; + total_size +} - return transmute(box); +// 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) } -/** -Thin wrapper around libc::malloc, none of the box header -stuff in exchange_alloc::malloc -*/ + +/// A wrapper around libc::malloc, aborting on out-of-memory +#[inline] pub unsafe fn malloc_raw(size: uint) -> *c_void { - let p = c_malloc(size as size_t); + let p = malloc(size as size_t); if p.is_null() { - fail!("Failure in malloc_raw: result ptr is null"); + // we need a non-allocating way to print an error here + abort(); } - inc_count(); p } -pub unsafe fn free(ptr: *c_void) { - assert!(ptr.is_not_null()); - dec_count(); - c_free(ptr); +/// 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 } -///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); + +// 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) } -fn inc_count() { - unsafe { - let exchange_count = &mut *exchange_count_ptr(); - atomic_xadd(exchange_count, 1); - } +#[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 } -fn dec_count() { - unsafe { - let exchange_count = &mut *exchange_count_ptr(); - atomic_xsub(exchange_count, 1); - } +// 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) } -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); - } - } +#[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 } -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; +// 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) } -// 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) +#[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 } -fn exchange_count_ptr() -> *mut int { - // XXX: Need mutable globals - unsafe { transmute(&rust_exchange_count) } +// 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) } -extern { - static rust_exchange_count: uintptr_t; +#[inline] +pub unsafe fn exchange_free(ptr: *c_char) { + free(ptr as *c_void); } diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index 55861f127bb..c6654e9dabe 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -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; diff --git a/src/libstd/rt/io/mem.rs b/src/libstd/rt/io/mem.rs index bd9cff76e57..c93945a6a9a 100644 --- a/src/libstd/rt/io/mem.rs +++ b/src/libstd/rt/io/mem.rs @@ -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); } diff --git a/src/libstd/rt/join_latch.rs b/src/libstd/rt/join_latch.rs index 79c0d5da9a4..8073c4a75b8 100644 --- a/src/libstd/rt/join_latch.rs +++ b/src/libstd/rt/join_latch.rs @@ -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; diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index f62c9fb2c66..c909bdb6285 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -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); diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs index 734be808797..6ef07577415 100644 --- a/src/libstd/rt/message_queue.rs +++ b/src/libstd/rt/message_queue.rs @@ -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(~[]) diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index aae194ae548..b70549c266a 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -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. diff --git a/src/libstd/rt/rc.rs b/src/libstd/rt/rc.rs index 2977d081508..18a5dd4a114 100644 --- a/src/libstd/rt/rc.rs +++ b/src/libstd/rt/rc.rs @@ -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 { diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 7d8c673636e..6e9aef77730 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -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; } } diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs index b0e87a62c8b..fbb516b2df4 100644 --- a/src/libstd/rt/stack.rs +++ b/src/libstd/rt/stack.rs @@ -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); diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index b2e4f0d4716..b4f4c1b3e35 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -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 diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs index bc290191310..98d08c060e0 100644 --- a/src/libstd/rt/thread.rs +++ b/src/libstd/rt/thread.rs @@ -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) } } } diff --git a/src/libstd/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs index 7187d2db41c..5041b559ecb 100644 --- a/src/libstd/rt/thread_local_storage.rs +++ b/src/libstd/rt/thread_local_storage.rs @@ -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)] diff --git a/src/libstd/rt/uv/net.rs b/src/libstd/rt/uv/net.rs index 4571747cebf..ada9aee35a7 100644 --- a/src/libstd/rt/uv/net.rs +++ b/src/libstd/rt/uv/net.rs @@ -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; diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index b1708e70733..69d14dbf9a1 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -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>(); diff --git a/src/libstd/rt/uvio.rs b/src/libstd/rt/uvio.rs index 070ccf7fb44..0187ad3abf5 100644 --- a/src/libstd/rt/uvio.rs +++ b/src/libstd/rt/uvio.rs @@ -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(||()); } diff --git a/src/libstd/rt/work_queue.rs b/src/libstd/rt/work_queue.rs index cfffc55a58c..00d27744268 100644 --- a/src/libstd/rt/work_queue.rs +++ b/src/libstd/rt/work_queue.rs @@ -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(~[]) diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 060de3f4d5d..9e5def253c7 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -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() { diff --git a/src/libstd/core.rc b/src/libstd/std.rs index 6911c00e55b..f0f3bcdd4e9 100644 --- a/src/libstd/core.rc +++ b/src/libstd/std.rs @@ -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; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 04f5247782b..4115cad6559 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -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)) } @@ -70,6 +68,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); diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index c71765f911a..d8b50c96fd8 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -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 diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index ad6f1d23c10..9f72f941bde 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -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; diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs index f6b14a51539..0956b76c970 100644 --- a/src/libstd/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -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); } } diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index b0fc6b2884f..ae8f1c2101d 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -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 diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index aea8cda6a21..bcb7e06bf1f 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -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 diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index 822aab0a027..d6e92dd679e 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -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) } } diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index 3e782e728fe..77701acd33e 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -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"); diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index aaeaa489834..8ce02d59ab1 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -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) => { diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index fefd55c3541..45702546278 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -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() } } } diff --git a/src/libstd/unicode.rs b/src/libstd/unicode.rs index f8f56c75a29..1e2d5c76fea 100644 --- a/src/libstd/unicode.rs +++ b/src/libstd/unicode.rs @@ -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) } + } diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs index 6e7a7e2b129..1e5ac305df3 100644 --- a/src/libstd/unstable/atomics.rs +++ b/src/libstd/unstable/atomics.rs @@ -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 { diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 64dd5bba6bc..e01f99adc94 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -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 } diff --git a/src/libstd/unstable/exchange_alloc.rs b/src/libstd/unstable/exchange_alloc.rs deleted file mode 100644 index 3b35c2fb804..00000000000 --- a/src/libstd/unstable/exchange_alloc.rs +++ /dev/null @@ -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; -} diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index d466488ce5e..624062a7ec4 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -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) { diff --git a/src/libstd/unstable/finally.rs b/src/libstd/unstable/finally.rs index b15bceddb1c..10db664450e 100644 --- a/src/libstd/unstable/finally.rs +++ b/src/libstd/unstable/finally.rs @@ -64,7 +64,7 @@ struct Finallyalizer<'self> { #[unsafe_destructor] impl<'self> Drop for Finallyalizer<'self> { - fn finalize(&self) { + fn drop(&self) { (self.dtor)(); } } diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs index f81252274c4..285a8114cc2 100644 --- a/src/libstd/unstable/global.rs +++ b/src/libstd/unstable/global.rs @@ -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); diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 13425007785..500143fb577 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -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)); diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 3a071af5d4c..66bb46b8991 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -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() { diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 162891124f6..0da05dd167d 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -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) diff --git a/src/libstd/util.rs b/src/libstd/util.rs index 2a5d44c9ce2..fd29d7dc14b 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -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); } + } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 4339153c43e..1180ac883e7 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -15,113 +15,45 @@ use cast::transmute; use cast; use container::{Container, Mutable}; +use cmp; use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; -use old_iter::BaseIter; -use old_iter; -use iterator::{Iterator}; +use iterator::{FromIterator, Iterator, IteratorUtil}; use iter::FromIter; use kinds::Copy; -use libc; +use libc::c_void; use num::Zero; -use old_iter::CopyableIter; +use ops::Add; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; use ptr::RawPtr; +use rt::global_heap::realloc_raw; use sys; +use sys::size_of; use uint; use unstable::intrinsics; +#[cfg(stage0)] +use intrinsic::{get_tydesc}; +#[cfg(not(stage0))] +use unstable::intrinsics::{get_tydesc, contains_managed}; use vec; use util; #[cfg(not(test))] use cmp::Equiv; -pub mod rustrt { - use libc; - use sys; - use vec::raw; - - #[abi = "cdecl"] - pub extern { - // These names are terrible. reserve_shared applies - // to ~[] and reserve_shared_actual applies to @[]. - #[fast_ffi] - unsafe fn vec_reserve_shared(t: *sys::TypeDesc, - v: *mut *mut raw::VecRepr, - n: libc::size_t); - } -} - /// Returns true if two vectors have the same length -pub fn same_length<T, U>(xs: &const [T], ys: &const [U]) -> bool { +pub fn same_length<T, U>(xs: &[T], ys: &[U]) -> bool { xs.len() == ys.len() } /** - * Reserves capacity for exactly `n` elements in the given vector. - * - * If the capacity for `v` is already equal to or greater than the requested - * capacity, then no action is taken. - * - * # Arguments - * - * * v - A vector - * * n - The number of elements to reserve space for - */ -#[inline] -pub fn reserve<T>(v: &mut ~[T], n: uint) { - // Only make the (slow) call into the runtime if we have to - use managed; - if capacity(v) < n { - unsafe { - let ptr: *mut *mut raw::VecRepr = cast::transmute(v); - let td = sys::get_type_desc::<T>(); - if ((**ptr).box_header.ref_count == - managed::raw::RC_MANAGED_UNIQUE) { - ::at_vec::raw::reserve_raw(td, ptr, n); - } else { - rustrt::vec_reserve_shared(td, ptr, n as libc::size_t); - } - } - } -} - -/** - * Reserves capacity for at least `n` elements in the given vector. - * - * This function will over-allocate in order to amortize the allocation costs - * in scenarios where the caller may need to repeatedly reserve additional - * space. - * - * If the capacity for `v` is already equal to or greater than the requested - * capacity, then no action is taken. - * - * # Arguments - * - * * v - A vector - * * n - The number of elements to reserve space for - */ -pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) { - reserve(v, uint::next_power_of_two(n)); -} - -/// Returns the number of elements the vector can hold without reallocating -#[inline] -pub fn capacity<T>(v: &const ~[T]) -> uint { - unsafe { - let repr: **raw::VecRepr = transmute(v); - (**repr).unboxed.alloc / sys::nonzero_size_of::<T>() - } -} - -/** * Creates and initializes an owned vector. * * Creates an owned 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] { unsafe { let mut v = with_capacity(n_elts); do as_mut_buf(v) |p, _len| { @@ -169,7 +101,7 @@ pub fn to_owned<T:Copy>(t: &[T]) -> ~[T] { /// Creates a new vector with a capacity of `capacity` pub fn with_capacity<T>(capacity: uint) -> ~[T] { let mut vec = ~[]; - reserve(&mut vec, capacity); + vec.reserve(capacity); vec } @@ -228,85 +160,6 @@ pub fn build_sized_opt<A>(size: Option<uint>, // Accessors -/// Returns the first element of a vector -pub fn head<'r,T>(v: &'r [T]) -> &'r T { - if v.len() == 0 { fail!("head: empty vector") } - &v[0] -} - -/// Returns `Some(x)` where `x` is the first element of the slice `v`, -/// or `None` if the vector is empty. -pub fn head_opt<'r,T>(v: &'r [T]) -> Option<&'r T> { - if v.len() == 0 { None } else { Some(&v[0]) } -} - -/// Returns a vector containing all but the first element of a slice -pub fn tail<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 1, v.len()) } - -/// Returns a vector containing all but the first `n` elements of a slice -pub fn tailn<'r,T>(v: &'r [T], n: uint) -> &'r [T] { slice(v, n, v.len()) } - -/// Returns a vector containing all but the last element of a slice -pub fn init<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 0, v.len() - 1) } - -/// Returns a vector containing all but the last `n' elements of a slice -pub fn initn<'r,T>(v: &'r [T], n: uint) -> &'r [T] { - slice(v, 0, v.len() - n) -} - -/// Returns the last element of the slice `v`, failing if the slice is empty. -pub fn last<'r,T>(v: &'r [T]) -> &'r T { - if v.len() == 0 { fail!("last: empty vector") } - &v[v.len() - 1] -} - -/// Returns `Some(x)` where `x` is the last element of the slice `v`, or -/// `None` if the vector is empty. -pub fn last_opt<'r,T>(v: &'r [T]) -> Option<&'r T> { - if v.len() == 0 { None } else { Some(&v[v.len() - 1]) } -} - -/// Return a slice that points into another slice. -#[inline] -pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { - assert!(start <= end); - assert!(end <= v.len()); - do as_imm_buf(v) |p, _len| { - unsafe { - transmute((ptr::offset(p, start), - (end - start) * sys::nonzero_size_of::<T>())) - } - } -} - -/// Return a slice that points into another slice. -#[inline] -pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) - -> &'r mut [T] { - assert!(start <= end); - assert!(end <= v.len()); - do as_mut_buf(v) |p, _len| { - unsafe { - transmute((ptr::mut_offset(p, start), - (end - start) * sys::nonzero_size_of::<T>())) - } - } -} - -/// Return a slice that points into another slice. -#[inline] -pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint) - -> &'r const [T] { - assert!(start <= end); - assert!(end <= v.len()); - do as_const_buf(v) |p, _len| { - unsafe { - transmute((ptr::const_offset(p, start), - (end - start) * sys::nonzero_size_of::<T>())) - } - } -} - /// Copies /// Split the vector `v` by applying each element against the predicate `f`. @@ -317,15 +170,15 @@ pub fn split<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] { let mut start = 0u; let mut result = ~[]; while start < ln { - match position_between(v, start, ln, f) { + match v.slice(start, ln).iter().position_(|t| f(t)) { None => break, Some(i) => { - result.push(slice(v, start, i).to_vec()); - start = i + 1u; + result.push(v.slice(start, start + i).to_owned()); + start += i + 1u; } } } - result.push(slice(v, start, ln).to_vec()); + result.push(v.slice(start, ln).to_owned()); result } @@ -341,17 +194,17 @@ pub fn splitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] { let mut count = n; let mut result = ~[]; while start < ln && count > 0u { - match position_between(v, start, ln, f) { + match v.slice(start, ln).iter().position_(|t| f(t)) { None => break, Some(i) => { - result.push(slice(v, start, i).to_vec()); + result.push(v.slice(start, start + i).to_owned()); // Make sure to skip the separator. - start = i + 1u; + start += i + 1u; count -= 1u; } } } - result.push(slice(v, start, ln).to_vec()); + result.push(v.slice(start, ln).to_owned()); result } @@ -366,16 +219,16 @@ pub fn rsplit<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] { let mut end = ln; let mut result = ~[]; while end > 0 { - match rposition_between(v, 0, end, f) { + match v.slice(0, end).rposition(|t| f(t)) { None => break, Some(i) => { - result.push(slice(v, i + 1, end).to_vec()); + result.push(v.slice(i + 1, end).to_owned()); end = i; } } } - result.push(slice(v, 0u, end).to_vec()); - reverse(result); + result.push(v.slice(0u, end).to_owned()); + result.reverse(); result } @@ -391,151 +244,21 @@ pub fn rsplitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] { let mut count = n; let mut result = ~[]; while end > 0u && count > 0u { - match rposition_between(v, 0u, end, f) { + match v.slice(0, end).rposition(|t| f(t)) { None => break, Some(i) => { - result.push(slice(v, i + 1u, end).to_vec()); + result.push(v.slice(i + 1u, end).to_owned()); // Make sure to skip the separator. end = i; count -= 1u; } } } - result.push(slice(v, 0u, end).to_vec()); - reverse(result); + result.push(v.slice(0u, end).to_owned()); + result.reverse(); result } -/** - * Partitions a vector into two new vectors: those that satisfies the - * predicate, and those that do not. - */ -pub fn partition<T>(v: ~[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) { - let mut lefts = ~[]; - let mut rights = ~[]; - - // FIXME (#4355 maybe): using v.consume here crashes - // do v.consume |_, elt| { - do consume(v) |_, elt| { - if f(&elt) { - lefts.push(elt); - } else { - rights.push(elt); - } - } - - (lefts, rights) -} - -/** - * Partitions a vector into two new vectors: those that satisfies the - * predicate, and those that do not. - */ -pub fn partitioned<T:Copy>(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) { - let mut lefts = ~[]; - let mut rights = ~[]; - - for each(v) |elt| { - if f(elt) { - lefts.push(copy *elt); - } else { - rights.push(copy *elt); - } - } - - (lefts, rights) -} - -// Mutators - -/// Removes the first element from a vector and return it -pub fn shift<T>(v: &mut ~[T]) -> T { - unsafe { - assert!(!v.is_empty()); - - if v.len() == 1 { return v.pop() } - - if v.len() == 2 { - let last = v.pop(); - let first = v.pop(); - v.push(last); - return first; - } - - let ln = v.len(); - let next_ln = v.len() - 1; - - // Save the last element. We're going to overwrite its position - let work_elt = v.pop(); - // We still should have room to work where what last element was - assert!(capacity(v) >= ln); - // Pretend like we have the original length so we can use - // the vector copy_memory to overwrite the hole we just made - raw::set_len(&mut *v, ln); - - // Memcopy the head element (the one we want) to the location we just - // popped. For the moment it unsafely exists at both the head and last - // positions - { - let first_slice = slice(*v, 0, 1); - let last_slice = slice(*v, next_ln, ln); - raw::copy_memory(transmute(last_slice), first_slice, 1); - } - - // Memcopy everything to the left one element - { - let init_slice = slice(*v, 0, next_ln); - let tail_slice = slice(*v, 1, ln); - raw::copy_memory(transmute(init_slice), - tail_slice, - next_ln); - } - - // Set the new length. Now the vector is back to normal - raw::set_len(&mut *v, next_ln); - - // Swap out the element we want from the end - let vp = raw::to_mut_ptr(*v); - let vp = ptr::mut_offset(vp, next_ln - 1); - - ptr::replace_ptr(vp, work_elt) - } -} - -/// Prepend an element to the vector -pub fn unshift<T>(v: &mut ~[T], x: T) { - let vv = util::replace(v, ~[x]); - v.push_all_move(vv); -} - -/// Insert an element at position i within v, shifting all -/// elements after position i one position to the right. -pub fn insert<T>(v: &mut ~[T], i: uint, x: T) { - let len = v.len(); - assert!(i <= len); - - v.push(x); - let mut j = len; - while j > i { - swap(*v, j, j - 1); - j -= 1; - } -} - -/// Remove and return the element at position i within v, shifting -/// all elements after position i one position to the left. -pub fn remove<T>(v: &mut ~[T], i: uint) -> T { - let len = v.len(); - assert!(i < len); - - let mut j = i; - while j < len - 1 { - swap(*v, j, j + 1); - j += 1; - } - v.pop() -} - /// Consumes all elements, in a vector, moving them out into the / closure /// provided. The vector is traversed from the start to the end. /// @@ -597,174 +320,12 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) { } } -/// Remove the last element from a vector and return it -pub fn pop<T>(v: &mut ~[T]) -> T { - let ln = v.len(); - if ln == 0 { - fail!("sorry, cannot vec::pop an empty vector") - } - let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]); - unsafe { - let val = ptr::replace_ptr(valptr, intrinsics::init()); - raw::set_len(v, ln - 1u); - val - } -} - -/** - * Remove an element from anywhere in the vector and return it, replacing it - * with the last element. This does not preserve ordering, but is O(1). - * - * Fails if index >= length. - */ -pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T { - let ln = v.len(); - if index >= ln { - fail!("vec::swap_remove - index %u >= length %u", index, ln); - } - if index < ln - 1 { - swap(*v, index, ln - 1); - } - v.pop() -} - -/// Append an element to a vector -#[inline] -pub fn push<T>(v: &mut ~[T], initval: T) { - unsafe { - let repr: **raw::VecRepr = transmute(&mut *v); - let fill = (**repr).unboxed.fill; - if (**repr).unboxed.alloc > fill { - push_fast(v, initval); - } - else { - push_slow(v, initval); - } - } -} - -// This doesn't bother to make sure we have space. -#[inline] // really pretty please -unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { - let repr: **mut raw::VecRepr = transmute(v); - let fill = (**repr).unboxed.fill; - (**repr).unboxed.fill += sys::nonzero_size_of::<T>(); - let p = to_unsafe_ptr(&((**repr).unboxed.data)); - let p = ptr::offset(p, fill) as *mut T; - intrinsics::move_val_init(&mut(*p), initval); -} - -#[inline(never)] -fn push_slow<T>(v: &mut ~[T], initval: T) { - let new_len = v.len() + 1; - reserve_at_least(&mut *v, new_len); - unsafe { push_fast(v, initval) } -} - -/// Iterates over the slice `rhs`, copies each element, and then appends it to -/// the vector provided `v`. The `rhs` vector is traversed in-order. -/// -/// # Example -/// -/// ~~~ {.rust} -/// let mut a = ~[1]; -/// vec::push_all(&mut a, [2, 3, 4]); -/// assert!(a == ~[1, 2, 3, 4]); -/// ~~~ -#[inline] -pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) { - let new_len = v.len() + rhs.len(); - reserve(&mut *v, new_len); - - for uint::range(0u, rhs.len()) |i| { - push(&mut *v, unsafe { raw::get(rhs, i) }) - } -} - -/// Takes ownership of the vector `rhs`, moving all elements into the specified -/// vector `v`. This does not copy any elements, and it is illegal to use the -/// `rhs` vector after calling this method (because it is moved here). -/// -/// # Example -/// -/// ~~~ {.rust} -/// let mut a = ~[~1]; -/// vec::push_all_move(&mut a, ~[~2, ~3, ~4]); -/// assert!(a == ~[~1, ~2, ~3, ~4]); -/// ~~~ -#[inline] -pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) { - let new_len = v.len() + rhs.len(); - reserve(&mut *v, new_len); - unsafe { - do as_mut_buf(rhs) |p, len| { - for uint::range(0, len) |i| { - let x = ptr::replace_ptr(ptr::mut_offset(p, i), - intrinsics::uninit()); - push(&mut *v, x); - } - } - raw::set_len(&mut rhs, 0); - } -} - -/// Shorten a vector, dropping excess elements. -pub fn truncate<T>(v: &mut ~[T], newlen: uint) { - do as_mut_buf(*v) |p, oldlen| { - assert!(newlen <= oldlen); - unsafe { - // This loop is optimized out for non-drop types. - for uint::range(newlen, oldlen) |i| { - ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit()); - } - } - } - unsafe { raw::set_len(&mut *v, newlen); } -} - -/** - * Remove consecutive repeated elements from a vector; if the vector is - * sorted, this removes all duplicates. - */ -pub fn dedup<T:Eq>(v: &mut ~[T]) { - unsafe { - if v.len() < 1 { return; } - let mut (last_written, next_to_read) = (0, 1); - do as_const_buf(*v) |p, ln| { - // We have a mutable reference to v, so we can make arbitrary - // changes. (cf. push and pop) - let p = p as *mut T; - // last_written < next_to_read <= ln - while next_to_read < ln { - // last_written < next_to_read < ln - if *ptr::mut_offset(p, next_to_read) == - *ptr::mut_offset(p, last_written) { - ptr::replace_ptr(ptr::mut_offset(p, next_to_read), - intrinsics::uninit()); - } else { - last_written += 1; - // last_written <= next_to_read < ln - if next_to_read != last_written { - ptr::swap_ptr(ptr::mut_offset(p, last_written), - ptr::mut_offset(p, next_to_read)); - } - } - // last_written <= next_to_read < ln - next_to_read += 1; - // last_written < next_to_read <= ln - } - } - // last_written < next_to_read == ln - raw::set_len(v, last_written + 1); - } -} - // Appending /// 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] { let mut v = lhs; v.push_all(rhs); v @@ -779,74 +340,8 @@ pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] { v } -/** - * Expands a vector in place, initializing the new elements to a given value - * - * # Arguments - * - * * v - The vector to grow - * * n - The number of elements to add - * * initval - The value for the new elements - */ -pub fn grow<T:Copy>(v: &mut ~[T], n: uint, initval: &T) { - let new_len = v.len() + n; - reserve_at_least(&mut *v, new_len); - let mut i: uint = 0u; - - while i < n { - v.push(copy *initval); - i += 1u; - } -} - -/** - * Expands a vector in place, initializing the new elements to the result of - * a function - * - * Function `init_op` is called `n` times with the values [0..`n`) - * - * # Arguments - * - * * v - The vector to grow - * * n - The number of elements to add - * * init_op - A function to call to retreive each appended element's - * value - */ -pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: old_iter::InitOp<T>) { - let new_len = v.len() + n; - reserve_at_least(&mut *v, new_len); - let mut i: uint = 0u; - while i < n { - v.push(op(i)); - i += 1u; - } -} - -/** - * Sets the value of a vector element at a given index, growing the vector as - * needed - * - * Sets the element at position `index` to `val`. If `index` is past the end - * of the vector, expands the vector by replicating `initval` to fill the - * intervening space. - */ -pub fn grow_set<T:Copy>(v: &mut ~[T], index: uint, initval: &T, val: T) { - let l = v.len(); - if index >= l { grow(&mut *v, index - l + 1u, initval); } - v[index] = val; -} - // Functional utilities -/// Apply a function to each element of a vector and return the results -pub fn map<T, U>(v: &[T], f: &fn(t: &T) -> U) -> ~[U] { - let mut result = with_capacity(v.len()); - for each(v) |elem| { - result.push(f(elem)); - } - result -} - /// Consumes a vector, mapping it into a different vector. This function takes /// ownership of the supplied vector `v`, moving each element into the closure /// provided to generate a new element. The vector of new elements is then @@ -861,43 +356,16 @@ pub fn map_consume<T, U>(v: ~[T], f: &fn(v: T) -> U) -> ~[U] { } result } - -/// Apply a function to each element of a vector and return the results -pub fn mapi<T, U>(v: &[T], f: &fn(uint, t: &T) -> U) -> ~[U] { - let mut i = 0; - do map(v) |e| { - i += 1; - f(i - 1, e) - } -} - /** * Apply a function to each element of a vector and return a concatenation * of each result vector */ pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] { let mut result = ~[]; - for each(v) |elem| { result.push_all_move(f(elem)); } + for v.iter().advance |elem| { result.push_all_move(f(elem)); } result } -/** - * Apply a function to each pair of elements and return the results. - * Equivalent to `map(zip(v0, v1), f)`. - */ -pub fn map_zip<T:Copy,U:Copy,V>(v0: &[T], v1: &[U], - f: &fn(t: &T, v: &U) -> V) -> ~[V] { - let v0_len = v0.len(); - if v0_len != v1.len() { fail!(); } - let mut u: ~[V] = ~[]; - let mut i = 0u; - while i < v0_len { - u.push(f(&v0[i], &v1[i])); - i += 1u; - } - u -} - pub fn filter_map<T, U>( v: ~[T], f: &fn(t: T) -> Option<U>) -> ~[U] @@ -930,7 +398,7 @@ pub fn filter_mapped<T, U: Copy>( */ let mut result = ~[]; - for each(v) |elem| { + for v.iter().advance |elem| { match f(elem) { None => {/* no-op */ } Some(result_elem) => { result.push(result_elem); } @@ -965,32 +433,12 @@ pub fn filter<T>(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] { */ pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] { let mut result = ~[]; - for each(v) |elem| { + for v.iter().advance |elem| { if f(elem) { result.push(copy *elem); } } result } -/** - * Like `filter()`, but in place. Preserves order of `v`. Linear time. - */ -pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) { - let len = v.len(); - let mut deleted: uint = 0; - - for uint::range(0, len) |i| { - if !f(&v[i]) { - deleted += 1; - } else if deleted > 0 { - swap(*v, i - deleted, i); - } - } - - if deleted > 0 { - v.truncate(len - deleted); - } -} - /// Flattens a vector of vectors of T into a single vector of T. pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat_vec() } @@ -1021,7 +469,7 @@ impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] { pub fn connect_vec(&self, sep: &T) -> ~[T] { let mut r = ~[]; let mut first = true; - for self.each |&inner| { + for self.iter().advance |&inner| { if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } @@ -1039,7 +487,7 @@ impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] { pub fn connect_vec(&self, sep: &T) -> ~[T] { let mut r = ~[]; let mut first = true; - for self.each |&inner| { + for self.iter().advance |&inner| { if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } @@ -1047,172 +495,6 @@ impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] { } } -/// Return true if a vector contains an element with the given value -pub fn contains<T:Eq>(v: &[T], x: &T) -> bool { - for each(v) |elt| { if *x == *elt { return true; } } - false -} - -/** - * Search for the first element that matches a given predicate - * - * Apply function `f` to each element of `v`, starting from the first. - * When function `f` returns true then an option containing the element - * is returned. If `f` matches no elements then none is returned. - */ -pub fn find<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> Option<T> { - find_between(v, 0u, v.len(), f) -} - -/** - * Search for the first element that matches a given predicate within a range - * - * Apply function `f` to each element of `v` within the range - * [`start`, `end`). When function `f` returns true then an option containing - * the element is returned. If `f` matches no elements then none is returned. - */ -pub fn find_between<T:Copy>(v: &[T], start: uint, end: uint, - f: &fn(t: &T) -> bool) -> Option<T> { - position_between(v, start, end, f).map(|i| copy v[*i]) -} - -/** - * Search for the last element that matches a given predicate - * - * Apply function `f` to each element of `v` in reverse order. When function - * `f` returns true then an option containing the element is returned. If `f` - * matches no elements then none is returned. - */ -pub fn rfind<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> Option<T> { - rfind_between(v, 0u, v.len(), f) -} - -/** - * Search for the last element that matches a given predicate within a range - * - * Apply function `f` to each element of `v` in reverse order within the range - * [`start`, `end`). When function `f` returns true then an option containing - * the element is returned. If `f` matches no elements then none is return. - */ -pub fn rfind_between<T:Copy>(v: &[T], - start: uint, - end: uint, - f: &fn(t: &T) -> bool) - -> Option<T> { - rposition_between(v, start, end, f).map(|i| copy v[*i]) -} - -/// Find the first index containing a matching value -pub fn position_elem<T:Eq>(v: &[T], x: &T) -> Option<uint> { - position(v, |y| *x == *y) -} - -/** - * Find the first index matching some predicate - * - * Apply function `f` to each element of `v`. When function `f` returns true - * then an option containing the index is returned. If `f` matches no elements - * then none is returned. - */ -pub fn position<T>(v: &[T], f: &fn(t: &T) -> bool) -> Option<uint> { - position_between(v, 0u, v.len(), f) -} - -/** - * Find the first index matching some predicate within a range - * - * Apply function `f` to each element of `v` between the range - * [`start`, `end`). When function `f` returns true then an option containing - * the index is returned. If `f` matches no elements then none is returned. - */ -pub fn position_between<T>(v: &[T], - start: uint, - end: uint, - f: &fn(t: &T) -> bool) - -> Option<uint> { - assert!(start <= end); - assert!(end <= v.len()); - let mut i = start; - while i < end { if f(&v[i]) { return Some::<uint>(i); } i += 1u; } - None -} - -/// Find the last index containing a matching value -pub fn rposition_elem<T:Eq>(v: &[T], x: &T) -> Option<uint> { - rposition(v, |y| *x == *y) -} - -/** - * Find the last index matching some predicate - * - * Apply function `f` to each element of `v` in reverse order. When function - * `f` returns true then an option containing the index is returned. If `f` - * matches no elements then none is returned. - */ -pub fn rposition<T>(v: &[T], f: &fn(t: &T) -> bool) -> Option<uint> { - rposition_between(v, 0u, v.len(), f) -} - -/** - * Find the last index matching some predicate within a range - * - * Apply function `f` to each element of `v` in reverse order between the - * range [`start`, `end`). When function `f` returns true then an option - * containing the index is returned. If `f` matches no elements then none is - * returned. - */ -pub fn rposition_between<T>(v: &[T], start: uint, end: uint, - f: &fn(t: &T) -> bool) -> Option<uint> { - assert!(start <= end); - assert!(end <= v.len()); - let mut i = end; - while i > start { - if f(&v[i - 1u]) { return Some::<uint>(i - 1u); } - i -= 1u; - } - None -} - - - -/** - * Binary search a sorted vector with a comparator function. - * - * The comparator should implement an order consistent with the sort - * order of the underlying vector, returning an order code that indicates - * whether its argument is `Less`, `Equal` or `Greater` the desired target. - * - * Returns the index where the comparator returned `Equal`, or `None` if - * not found. - */ -pub fn bsearch<T>(v: &[T], f: &fn(&T) -> Ordering) -> Option<uint> { - let mut base : uint = 0; - let mut lim : uint = v.len(); - - while lim != 0 { - let ix = base + (lim >> 1); - match f(&v[ix]) { - Equal => return Some(ix), - Less => { - base = ix + 1; - lim -= 1; - } - Greater => () - } - lim >>= 1; - } - return None; -} - -/** - * Binary search a sorted vector for a given element. - * - * Returns the index of the element or None if not found. - */ -pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> { - bsearch(v, |p| p.cmp(x)) -} - // FIXME: if issue #586 gets implemented, could have a postcondition // saying the two result lists have the same length -- or, could // return a nominal record with a constraint saying that, instead of @@ -1221,8 +503,9 @@ pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> { * Convert a vector of pairs into a pair of vectors, by reference. As unzip(). */ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) { - let mut (ts, us) = (~[], ~[]); - for each(v) |p| { + let mut ts = ~[]; + let mut us = ~[]; + for v.iter().advance |p| { let (t, u) = copy *p; ts.push(t); us.push(u); @@ -1239,7 +522,8 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) { * of the i-th tuple of the input vector. */ pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) { - let mut (ts, us) = (~[], ~[]); + let mut ts = ~[]; + let mut us = ~[]; do consume(v) |_i, p| { let (t, u) = p; ts.push(t); @@ -1251,7 +535,7 @@ pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) { /** * Convert two vectors to a vector of pairs, by reference. As zip(). */ -pub fn zip_slice<T:Copy,U:Copy>(v: &const [T], u: &const [U]) +pub fn zip_slice<T:Copy,U:Copy>(v: &[T], u: &[U]) -> ~[(T, U)] { let mut zipped = ~[]; let sz = v.len(); @@ -1278,80 +562,12 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { w.push((v.pop(),u.pop())); i -= 1; } - reverse(w); + w.reverse(); w } -/** - * Swaps two elements in a vector - * - * # Arguments - * - * * v The input vector - * * a - The index of the first element - * * b - The index of the second element - */ -#[inline] -pub fn swap<T>(v: &mut [T], a: uint, b: uint) { - unsafe { - // Can't take two mutable loans from one vector, so instead just cast - // them to their raw pointers to do the swap - let pa: *mut T = &mut v[a]; - let pb: *mut T = &mut v[b]; - ptr::swap_ptr(pa, pb); - } -} - -/// Reverse the order of elements in a vector, in place -pub fn reverse<T>(v: &mut [T]) { - let mut i: uint = 0; - let ln = v.len(); - while i < ln / 2 { - swap(v, i, ln - i - 1); - i += 1; - } -} - -/** - * Reverse part of a vector in place. - * - * Reverse the elements in the vector between `start` and `end - 1`. - * - * If either start or end do not represent valid positions in the vector, the - * vector is returned unchanged. - * - * # Arguments - * - * * `v` - The mutable vector to be modified - * - * * `start` - Index of the first element of the slice - * - * * `end` - Index one past the final element to be reversed. - * - * # Example - * - * Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call: - * - * ~~~ {.rust} - * reverse_part(v, 1, 4); - * ~~~ - * - * `v` now contains `[1,4,3,2,5]`. - */ -pub fn reverse_part<T>(v: &mut [T], start: uint, end : uint) { - let sz = v.len(); - if start >= sz || end > sz { return; } - let mut i = start; - let mut j = end - 1; - while i < j { - vec::swap(v, i, j); - i += 1; - j -= 1; - } -} - /// Returns a vector with the order of elements reversed -pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] { +pub fn reversed<T:Copy>(v: &[T]) -> ~[T] { let mut rs: ~[T] = ~[]; let mut i = v.len(); if i == 0 { return (rs); } else { i -= 1; } @@ -1361,99 +577,6 @@ pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] { } /** - * Iterates over a vector, yielding each element to a closure. - * - * # Arguments - * - * * `v` - A vector, to be iterated over - * * `f` - A closure to do the iterating. Within this closure, return true to - * * continue iterating, false to break. - * - * # Examples - * - * ~~~ {.rust} - * [1,2,3].each(|&i| { - * io::println(int::str(i)); - * true - * }); - * ~~~ - * - * ~~~ {.rust} - * [1,2,3,4,5].each(|&i| { - * if i < 4 { - * io::println(int::str(i)); - * true - * } - * else { - * false - * } - * }); - * ~~~ - * - * You probably will want to use each with a `for`/`do` expression, depending - * on your iteration needs: - * - * ~~~ {.rust} - * for [1,2,3].each |&i| { - * io::println(int::str(i)); - * } - * ~~~ - */ -#[inline] -pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { - // ^^^^ - // NB---this CANNOT be &const [T]! The reason - // is that you are passing it to `f()` using - // an immutable. - - let mut broke = false; - do as_imm_buf(v) |p, n| { - let mut n = n; - let mut p = p; - while n > 0u { - unsafe { - let q = cast::copy_lifetime_vec(v, &*p); - if !f(q) { break; } - p = ptr::offset(p, 1u); - } - n -= 1u; - } - broke = n > 0; - } - return !broke; -} - -/// Like `each()`, but for the case where you have a vector that *may or may -/// not* have mutable contents. -#[inline] -pub fn each_const<T>(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { - let mut i = 0; - let n = v.len(); - while i < n { - if !f(&const v[i]) { - return false; - } - i += 1; - } - return true; -} - -/** - * Iterates over a vector's elements and indices - * - * Return true to continue, false to break. - */ -#[inline] -pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { - let mut i = 0; - for each(v) |p| { - if !f(i, p) { return false; } - i += 1; - } - return true; -} - -/** * Iterate over all permutations of vector `v`. * * Permutations are produced in lexicographic order with respect to the order @@ -1498,8 +621,8 @@ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> } // swap indices[k] and indices[l]; sort indices[k+1..] // (they're just reversed) - vec::swap(indices, k, l); - reverse_part(indices, k+1, length); + indices.swap(k, l); + indices.mut_slice(k+1, length).reverse(); // fixup permutation based on indices for uint::range(k, length) |i| { permutation[i] = copy values[indices[i]]; @@ -1554,16 +677,6 @@ pub fn as_imm_buf<T,U>(s: &[T], } } -/// Similar to `as_imm_buf` but passing a `*const T` -#[inline] -pub fn as_const_buf<T,U>(s: &const [T], f: &fn(*const T, uint) -> U) -> U { - unsafe { - let v : *(*const T,uint) = transmute(&s); - let (buf,len) = *v; - f(buf, len / sys::nonzero_size_of::<T>()) - } -} - /// Similar to `as_imm_buf` but passing a `*mut T` #[inline] pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { @@ -1744,30 +857,24 @@ impl<T:Ord> Ord for @[T] { } #[cfg(not(test))] -pub mod traits { - use kinds::Copy; - use ops::Add; - use vec::append; - - impl<'self,T:Copy> Add<&'self const [T],~[T]> for ~[T] { - #[inline] - fn add(&self, rhs: & &'self const [T]) -> ~[T] { - append(copy *self, (*rhs)) - } +impl<'self,T:Copy> Add<&'self [T], ~[T]> for ~[T] { + #[inline] + fn add(&self, rhs: & &'self [T]) -> ~[T] { + append(copy *self, (*rhs)) } } -impl<'self, T> Container for &'self const [T] { +impl<'self, T> Container for &'self [T] { /// Returns true if a vector contains no elements #[inline] fn is_empty(&self) -> bool { - as_const_buf(*self, |_p, len| len == 0u) + as_imm_buf(*self, |_p, len| len == 0u) } /// Returns the length of a vector #[inline] fn len(&self) -> uint { - as_const_buf(*self, |_p, len| len) + as_imm_buf(*self, |_p, len| len) } } @@ -1775,13 +882,13 @@ impl<T> Container for ~[T] { /// Returns true if a vector contains no elements #[inline] fn is_empty(&self) -> bool { - as_const_buf(*self, |_p, len| len == 0u) + as_imm_buf(*self, |_p, len| len == 0u) } /// Returns the length of a vector #[inline] fn len(&self) -> uint { - as_const_buf(*self, |_p, len| len) + as_imm_buf(*self, |_p, len| len) } } @@ -1795,13 +902,11 @@ impl<'self,T:Copy> CopyableVector<T> for &'self [T] { /// Returns a copy of `v`. #[inline] fn to_owned(&self) -> ~[T] { - let mut result = ~[]; - reserve(&mut result, self.len()); - for self.each |e| { + let mut result = with_capacity(self.len()); + for self.iter().advance |e| { result.push(copy *e); } result - } } @@ -1818,14 +923,14 @@ pub trait ImmutableVector<'self, T> { fn initn(&self, n: uint) -> &'self [T]; fn last(&self) -> &'self T; fn last_opt(&self) -> Option<&'self T>; - fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>; fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>; - fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U]; - fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U]; - fn map_r<U>(&self, f: &fn(x: &T) -> U) -> ~[U]; fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U]; unsafe fn unsafe_ref(&self, index: uint) -> *T; + + fn bsearch(&self, f: &fn(&T) -> Ordering) -> Option<uint>; + + fn map<U>(&self, &fn(t: &T) -> U) -> ~[U]; } /// Extension methods for vectors @@ -1833,7 +938,14 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { /// Return a slice that points into another slice. #[inline] fn slice(&self, start: uint, end: uint) -> &'self [T] { - slice(*self, start, end) + assert!(start <= end); + assert!(end <= self.len()); + do as_imm_buf(*self) |p, _len| { + unsafe { + transmute((ptr::offset(p, start), + (end - start) * sys::nonzero_size_of::<T>())) + } + } } #[inline] @@ -1856,46 +968,48 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { /// Returns the first element of a vector, failing if the vector is empty. #[inline] - fn head(&self) -> &'self T { head(*self) } + fn head(&self) -> &'self T { + if self.len() == 0 { fail!("head: empty vector") } + &self[0] + } - /// Returns the first element of a vector + /// Returns the first element of a vector, or `None` if it is empty #[inline] - fn head_opt(&self) -> Option<&'self T> { head_opt(*self) } + fn head_opt(&self) -> Option<&'self T> { + if self.len() == 0 { None } else { Some(&self[0]) } + } /// Returns all but the first element of a vector #[inline] - fn tail(&self) -> &'self [T] { tail(*self) } + fn tail(&self) -> &'self [T] { self.slice(1, self.len()) } /// Returns all but the first `n' elements of a vector #[inline] - fn tailn(&self, n: uint) -> &'self [T] { tailn(*self, n) } + fn tailn(&self, n: uint) -> &'self [T] { self.slice(n, self.len()) } - /// Returns all but the last elemnt of a vector + /// Returns all but the last element of a vector #[inline] - fn init(&self) -> &'self [T] { init(*self) } + fn init(&self) -> &'self [T] { + self.slice(0, self.len() - 1) + } /// Returns all but the last `n' elemnts of a vector #[inline] - fn initn(&self, n: uint) -> &'self [T] { initn(*self, n) } - - /// Returns the last element of a `v`, failing if the vector is empty. - #[inline] - fn last(&self) -> &'self T { last(*self) } + fn initn(&self, n: uint) -> &'self [T] { + self.slice(0, self.len() - n) + } - /// Returns the last element of a `v`, failing if the vector is empty. + /// Returns the last element of a vector, failing if the vector is empty. #[inline] - fn last_opt(&self) -> Option<&'self T> { last_opt(*self) } + fn last(&self) -> &'self T { + if self.len() == 0 { fail!("last: empty vector") } + &self[self.len() - 1] + } - /** - * Find the first index matching some predicate - * - * Apply function `f` to each element of `v`. When function `f` returns - * true then an option containing the index is returned. If `f` matches no - * elements then none is returned. - */ + /// Returns the last element of a vector, or `None` if it is empty. #[inline] - fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint> { - position(*self, f) + fn last_opt(&self) -> Option<&'self T> { + if self.len() == 0 { None } else { Some(&self[self.len() - 1]) } } /** @@ -1903,34 +1017,14 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { * * Apply function `f` to each element of `v` in reverse order. When * function `f` returns true then an option containing the index is - * returned. If `f` matches no elements then none is returned. + * returned. If `f` matches no elements then None is returned. */ #[inline] fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> { - rposition(*self, f) - } - - /// Apply a function to each element of a vector and return the results - #[inline] - fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] { map(*self, f) } - - /** - * Apply a function to the index and value of each element in the vector - * and return the results - */ - fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U] { - mapi(*self, f) - } - - #[inline] - fn map_r<U>(&self, f: &fn(x: &T) -> U) -> ~[U] { - let mut r = ~[]; - let mut i = 0; - while i < self.len() { - r.push(f(&self[i])); - i += 1; + for self.rev_iter().enumerate().advance |(i, t)| { + if f(t) { return Some(self.len() - i - 1); } } - r + None } /** @@ -1959,32 +1053,90 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { let (ptr, _): (*T, uint) = transmute(*self); ptr.offset(index) } + + /** + * Binary search a sorted vector with a comparator function. + * + * The comparator should implement an order consistent with the sort + * order of the underlying vector, returning an order code that indicates + * whether its argument is `Less`, `Equal` or `Greater` the desired target. + * + * Returns the index where the comparator returned `Equal`, or `None` if + * not found. + */ + fn bsearch(&self, f: &fn(&T) -> Ordering) -> Option<uint> { + let mut base : uint = 0; + let mut lim : uint = self.len(); + + while lim != 0 { + let ix = base + (lim >> 1); + match f(&self[ix]) { + Equal => return Some(ix), + Less => { + base = ix + 1; + lim -= 1; + } + Greater => () + } + lim >>= 1; + } + return None; + } + + /// Deprecated, use iterators where possible + /// (`self.iter().transform(f)`). Apply a function to each element + /// of a vector and return the results. + fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] { + self.iter().transform(f).collect() + } } #[allow(missing_doc)] pub trait ImmutableEqVector<T:Eq> { fn position_elem(&self, t: &T) -> Option<uint>; fn rposition_elem(&self, t: &T) -> Option<uint>; + fn contains(&self, x: &T) -> bool; } impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] { /// Find the first index containing a matching value #[inline] fn position_elem(&self, x: &T) -> Option<uint> { - position_elem(*self, x) + self.iter().position_(|y| *x == *y) } /// Find the last index containing a matching value #[inline] fn rposition_elem(&self, t: &T) -> Option<uint> { - rposition_elem(*self, t) + self.rposition(|x| *x == *t) + } + + /// Return true if a vector contains an element with the given value + fn contains(&self, x: &T) -> bool { + for self.iter().advance |elt| { if *x == *elt { return true; } } + false + } +} + +#[allow(missing_doc)] +pub trait ImmutableTotalOrdVector<T: TotalOrd> { + fn bsearch_elem(&self, x: &T) -> Option<uint>; +} + +impl<'self, T: TotalOrd> ImmutableTotalOrdVector<T> for &'self [T] { + /** + * Binary search a sorted vector for a given element. + * + * Returns the index of the element or None if not found. + */ + fn bsearch_elem(&self, x: &T) -> Option<uint> { + self.bsearch(|p| p.cmp(x)) } } #[allow(missing_doc)] pub trait ImmutableCopyableVector<T> { fn filtered(&self, f: &fn(&T) -> bool) -> ~[T]; - fn rfind(&self, f: &fn(t: &T) -> bool) -> Option<T>; fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]); unsafe fn unsafe_get(&self, elem: uint) -> T; } @@ -2004,24 +1156,23 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { } /** - * Search for the last element that matches a given predicate - * - * Apply function `f` to each element of `v` in reverse order. When - * function `f` returns true then an option containing the element is - * returned. If `f` matches no elements then none is returned. - */ - #[inline] - fn rfind(&self, f: &fn(t: &T) -> bool) -> Option<T> { - rfind(*self, f) - } - - /** * Partitions the vector into those that satisfies the predicate, and * those that do not. */ #[inline] fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]) { - partitioned(*self, f) + let mut lefts = ~[]; + let mut rights = ~[]; + + for self.iter().advance |elt| { + if f(elt) { + lefts.push(copy *elt); + } else { + rights.push(copy *elt); + } + } + + (lefts, rights) } /// Returns the element at the given index, without doing bounds checking. @@ -2033,7 +1184,13 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { #[allow(missing_doc)] pub trait OwnedVector<T> { + fn reserve(&mut self, n: uint); + fn reserve_at_least(&mut self, n: uint); + fn capacity(&self) -> uint; + fn push(&mut self, t: T); + unsafe fn push_fast(&mut self, t: T); + fn push_all_move(&mut self, rhs: ~[T]); fn pop(&mut self) -> T; fn shift(&mut self) -> T; @@ -2047,58 +1204,316 @@ pub trait OwnedVector<T> { fn consume_reverse(self, f: &fn(uint, v: T)); fn filter(self, f: &fn(t: &T) -> bool) -> ~[T]; fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]); - fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>); + fn grow_fn(&mut self, n: uint, op: &fn(uint) -> T); } impl<T> OwnedVector<T> for ~[T] { + /** + * Reserves capacity for exactly `n` elements in the given vector. + * + * If the capacity for `self` is already equal to or greater than the requested + * capacity, then no action is taken. + * + * # Arguments + * + * * n - The number of elements to reserve space for + */ #[inline] - fn push(&mut self, t: T) { - push(self, t); + #[cfg(stage0)] + fn reserve(&mut self, n: uint) { + // Only make the (slow) call into the runtime if we have to + use managed; + if self.capacity() < n { + unsafe { + let ptr: *mut *mut raw::VecRepr = cast::transmute(self); + let td = get_tydesc::<T>(); + if ((**ptr).box_header.ref_count == + managed::raw::RC_MANAGED_UNIQUE) { + // XXX transmute shouldn't be necessary + let td = cast::transmute(td); + ::at_vec::raw::reserve_raw(td, ptr, n); + } else { + let alloc = n * sys::nonzero_size_of::<T>(); + *ptr = realloc_raw(*ptr as *mut c_void, alloc + size_of::<raw::VecRepr>()) + as *mut raw::VecRepr; + (**ptr).unboxed.alloc = alloc; + } + } + } + } + + /** + * Reserves capacity for exactly `n` elements in the given vector. + * + * If the capacity for `self` is already equal to or greater than the requested + * capacity, then no action is taken. + * + * # Arguments + * + * * n - The number of elements to reserve space for + */ + #[inline] + #[cfg(not(stage0))] + fn reserve(&mut self, n: uint) { + // Only make the (slow) call into the runtime if we have to + if self.capacity() < n { + unsafe { + let ptr: *mut *mut raw::VecRepr = cast::transmute(self); + let td = get_tydesc::<T>(); + if contains_managed::<T>() { + ::at_vec::raw::reserve_raw(td, ptr, n); + } else { + let alloc = n * sys::nonzero_size_of::<T>(); + *ptr = realloc_raw(*ptr as *mut c_void, alloc + size_of::<raw::VecRepr>()) + as *mut raw::VecRepr; + (**ptr).unboxed.alloc = alloc; + } + } + } + } + + /** + * Reserves capacity for at least `n` elements in the given vector. + * + * This function will over-allocate in order to amortize the allocation costs + * in scenarios where the caller may need to repeatedly reserve additional + * space. + * + * If the capacity for `self` is already equal to or greater than the requested + * capacity, then no action is taken. + * + * # Arguments + * + * * n - The number of elements to reserve space for + */ + fn reserve_at_least(&mut self, n: uint) { + self.reserve(uint::next_power_of_two(n)); } + /// Returns the number of elements the vector can hold without reallocating. #[inline] - fn push_all_move(&mut self, rhs: ~[T]) { - push_all_move(self, rhs); + fn capacity(&self) -> uint { + unsafe { + let repr: **raw::VecRepr = transmute(self); + (**repr).unboxed.alloc / sys::nonzero_size_of::<T>() + } } + /// Append an element to a vector #[inline] + fn push(&mut self, t: T) { + unsafe { + let repr: **raw::VecRepr = transmute(&mut *self); + let fill = (**repr).unboxed.fill; + if (**repr).unboxed.alloc <= fill { + // need more space + reserve_no_inline(self); + } + + self.push_fast(t); + } + + // this peculiar function is because reserve_at_least is very + // large (because of reserve), and will be inlined, which + // makes push too large. + #[inline(never)] + fn reserve_no_inline<T>(v: &mut ~[T]) { + let new_len = v.len() + 1; + v.reserve_at_least(new_len); + } + } + + // This doesn't bother to make sure we have space. + #[inline] // really pretty please + unsafe fn push_fast(&mut self, t: T) { + let repr: **mut raw::VecRepr = transmute(self); + let fill = (**repr).unboxed.fill; + (**repr).unboxed.fill += sys::nonzero_size_of::<T>(); + let p = to_unsafe_ptr(&((**repr).unboxed.data)); + let p = ptr::offset(p, fill) as *mut T; + intrinsics::move_val_init(&mut(*p), t); + } + + /// Takes ownership of the vector `rhs`, moving all elements into + /// the current vector. This does not copy any elements, and it is + /// illegal to use the `rhs` vector after calling this method + /// (because it is moved here). + /// + /// # Example + /// + /// ~~~ {.rust} + /// let mut a = ~[~1]; + /// a.push_all_move(~[~2, ~3, ~4]); + /// assert!(a == ~[~1, ~2, ~3, ~4]); + /// ~~~ + #[inline] + fn push_all_move(&mut self, mut rhs: ~[T]) { + let new_len = self.len() + rhs.len(); + self.reserve(new_len); + unsafe { + do as_mut_buf(rhs) |p, len| { + for uint::range(0, len) |i| { + let x = ptr::replace_ptr(ptr::mut_offset(p, i), + intrinsics::uninit()); + self.push(x); + } + } + raw::set_len(&mut rhs, 0); + } + } + + /// Remove the last element from a vector and return it fn pop(&mut self) -> T { - pop(self) + let ln = self.len(); + if ln == 0 { + fail!("sorry, cannot pop an empty vector") + } + let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]); + unsafe { + let val = ptr::replace_ptr(valptr, intrinsics::init()); + raw::set_len(self, ln - 1u); + val + } } - #[inline] + /// Removes the first element from a vector and return it fn shift(&mut self) -> T { - shift(self) + unsafe { + assert!(!self.is_empty()); + + if self.len() == 1 { return self.pop() } + + if self.len() == 2 { + let last = self.pop(); + let first = self.pop(); + self.push(last); + return first; + } + + let ln = self.len(); + let next_ln = self.len() - 1; + + // Save the last element. We're going to overwrite its position + let work_elt = self.pop(); + // We still should have room to work where what last element was + assert!(self.capacity() >= ln); + // Pretend like we have the original length so we can use + // the vector copy_memory to overwrite the hole we just made + raw::set_len(self, ln); + + // Memcopy the head element (the one we want) to the location we just + // popped. For the moment it unsafely exists at both the head and last + // positions + { + let first_slice = self.slice(0, 1); + let last_slice = self.slice(next_ln, ln); + raw::copy_memory(transmute(last_slice), first_slice, 1); + } + + // Memcopy everything to the left one element + { + let init_slice = self.slice(0, next_ln); + let tail_slice = self.slice(1, ln); + raw::copy_memory(transmute(init_slice), + tail_slice, + next_ln); + } + + // Set the new length. Now the vector is back to normal + raw::set_len(self, next_ln); + + // Swap out the element we want from the end + let vp = raw::to_mut_ptr(*self); + let vp = ptr::mut_offset(vp, next_ln - 1); + + ptr::replace_ptr(vp, work_elt) + } } - #[inline] + /// Prepend an element to the vector fn unshift(&mut self, x: T) { - unshift(self, x) + let v = util::replace(self, ~[x]); + self.push_all_move(v); } - #[inline] + /// Insert an element at position i within v, shifting all + /// elements after position i one position to the right. fn insert(&mut self, i: uint, x:T) { - insert(self, i, x) + let len = self.len(); + assert!(i <= len); + + self.push(x); + let mut j = len; + while j > i { + self.swap(j, j - 1); + j -= 1; + } } - #[inline] + /// Remove and return the element at position i within v, shifting + /// all elements after position i one position to the left. fn remove(&mut self, i: uint) -> T { - remove(self, i) + let len = self.len(); + assert!(i < len); + + let mut j = i; + while j < len - 1 { + self.swap(j, j + 1); + j += 1; + } + self.pop() } - #[inline] + /** + * Remove an element from anywhere in the vector and return it, replacing it + * with the last element. This does not preserve ordering, but is O(1). + * + * Fails if index >= length. + */ fn swap_remove(&mut self, index: uint) -> T { - swap_remove(self, index) + let ln = self.len(); + if index >= ln { + fail!("vec::swap_remove - index %u >= length %u", index, ln); + } + if index < ln - 1 { + self.swap(index, ln - 1); + } + self.pop() } - #[inline] + /// Shorten a vector, dropping excess elements. fn truncate(&mut self, newlen: uint) { - truncate(self, newlen); + do as_mut_buf(*self) |p, oldlen| { + assert!(newlen <= oldlen); + unsafe { + // This loop is optimized out for non-drop types. + for uint::range(newlen, oldlen) |i| { + ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit()); + } + } + } + unsafe { raw::set_len(self, newlen); } } - #[inline] + + /** + * Like `filter()`, but in place. Preserves order of `v`. Linear time. + */ fn retain(&mut self, f: &fn(t: &T) -> bool) { - retain(self, f); + let len = self.len(); + let mut deleted: uint = 0; + + for uint::range(0, len) |i| { + if !f(&self[i]) { + deleted += 1; + } else if deleted > 0 { + self.swap(i - deleted, i); + } + } + + if deleted > 0 { + self.truncate(len - deleted); + } } #[inline] @@ -2122,12 +1537,40 @@ impl<T> OwnedVector<T> for ~[T] { */ #[inline] fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]) { - partition(self, f) + let mut lefts = ~[]; + let mut rights = ~[]; + + do self.consume |_, elt| { + if f(&elt) { + lefts.push(elt); + } else { + rights.push(elt); + } + } + + (lefts, rights) } - #[inline] - fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>) { - grow_fn(self, n, op); + /** + * Expands a vector in place, initializing the new elements to the result of + * a function + * + * Function `init_op` is called `n` times with the values [0..`n`) + * + * # Arguments + * + * * n - The number of elements to add + * * init_op - A function to call to retreive each appended element's + * value + */ + fn grow_fn(&mut self, n: uint, op: &fn(uint) -> T) { + let new_len = self.len() + n; + self.reserve_at_least(new_len); + let mut i: uint = 0u; + while i < n { + self.push(op(i)); + i += 1u; + } } } @@ -2138,37 +1581,105 @@ impl<T> Mutable for ~[T] { #[allow(missing_doc)] pub trait OwnedCopyableVector<T:Copy> { - fn push_all(&mut self, rhs: &const [T]); + fn push_all(&mut self, rhs: &[T]); fn grow(&mut self, n: uint, initval: &T); fn grow_set(&mut self, index: uint, initval: &T, val: T); } impl<T:Copy> OwnedCopyableVector<T> for ~[T] { + /// Iterates over the slice `rhs`, copies each element, and then appends it to + /// the vector provided `v`. The `rhs` vector is traversed in-order. + /// + /// # Example + /// + /// ~~~ {.rust} + /// let mut a = ~[1]; + /// a.push_all([2, 3, 4]); + /// assert!(a == ~[1, 2, 3, 4]); + /// ~~~ #[inline] - fn push_all(&mut self, rhs: &const [T]) { - push_all(self, rhs); + fn push_all(&mut self, rhs: &[T]) { + let new_len = self.len() + rhs.len(); + self.reserve(new_len); + + for uint::range(0u, rhs.len()) |i| { + self.push(unsafe { raw::get(rhs, i) }) + } } - #[inline] + /** + * Expands a vector in place, initializing the new elements to a given value + * + * # Arguments + * + * * n - The number of elements to add + * * initval - The value for the new elements + */ fn grow(&mut self, n: uint, initval: &T) { - grow(self, n, initval); + let new_len = self.len() + n; + self.reserve_at_least(new_len); + let mut i: uint = 0u; + + while i < n { + self.push(copy *initval); + i += 1u; + } } - #[inline] + /** + * Sets the value of a vector element at a given index, growing the vector as + * needed + * + * Sets the element at position `index` to `val`. If `index` is past the end + * of the vector, expands the vector by replicating `initval` to fill the + * intervening space. + */ fn grow_set(&mut self, index: uint, initval: &T, val: T) { - grow_set(self, index, initval, val); + let l = self.len(); + if index >= l { self.grow(index - l + 1u, initval); } + self[index] = val; } } #[allow(missing_doc)] -trait OwnedEqVector<T:Eq> { +pub trait OwnedEqVector<T:Eq> { fn dedup(&mut self); } impl<T:Eq> OwnedEqVector<T> for ~[T] { - #[inline] - fn dedup(&mut self) { - dedup(self) + /** + * Remove consecutive repeated elements from a vector; if the vector is + * sorted, this removes all duplicates. + */ + pub fn dedup(&mut self) { + unsafe { + if self.len() == 0 { return; } + let mut last_written = 0; + let mut next_to_read = 1; + do as_mut_buf(*self) |p, ln| { + // last_written < next_to_read <= ln + while next_to_read < ln { + // last_written < next_to_read < ln + if *ptr::mut_offset(p, next_to_read) == + *ptr::mut_offset(p, last_written) { + ptr::replace_ptr(ptr::mut_offset(p, next_to_read), + intrinsics::uninit()); + } else { + last_written += 1; + // last_written <= next_to_read < ln + if next_to_read != last_written { + ptr::swap_ptr(ptr::mut_offset(p, last_written), + ptr::mut_offset(p, next_to_read)); + } + } + // last_written <= next_to_read < ln + next_to_read += 1; + // last_written < next_to_read <= ln + } + } + // last_written < next_to_read == ln + raw::set_len(self, last_written + 1); + } } } @@ -2178,14 +1689,41 @@ pub trait MutableVector<'self, T> { fn mut_iter(self) -> VecMutIterator<'self, T>; fn mut_rev_iter(self) -> VecMutRevIterator<'self, T>; + fn swap(self, a: uint, b: uint); + + fn reverse(self); + + /** + * Consumes `src` and moves as many elements as it can into `self` + * from the range [start,end). + * + * Returns the number of elements copied (the shorter of self.len() + * and end - start). + * + * # Arguments + * + * * src - A mutable vector of `T` + * * start - The index into `src` to start copying from + * * end - The index into `str` to stop copying from + */ + fn move_from(self, src: ~[T], start: uint, end: uint) -> uint; + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T; unsafe fn unsafe_set(&self, index: uint, val: T); } impl<'self,T> MutableVector<'self, T> for &'self mut [T] { + /// Return a slice that points into another slice. #[inline] fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] { - mut_slice(self, start, end) + assert!(start <= end); + assert!(end <= self.len()); + do as_mut_buf(self) |p, _len| { + unsafe { + transmute((ptr::mut_offset(p, start), + (end - start) * sys::nonzero_size_of::<T>())) + } + } } #[inline] @@ -2206,6 +1744,42 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { } } + /** + * Swaps two elements in a vector + * + * # Arguments + * + * * a - The index of the first element + * * b - The index of the second element + */ + fn swap(self, a: uint, b: uint) { + unsafe { + // Can't take two mutable loans from one vector, so instead just cast + // them to their raw pointers to do the swap + let pa: *mut T = &mut self[a]; + let pb: *mut T = &mut self[b]; + ptr::swap_ptr(pa, pb); + } + } + + /// Reverse the order of elements in a vector, in place + fn reverse(self) { + let mut i: uint = 0; + let ln = self.len(); + while i < ln / 2 { + self.swap(i, ln - i - 1); + i += 1; + } + } + + #[inline] + fn move_from(self, mut src: ~[T], start: uint, end: uint) -> uint { + for self.mut_iter().zip(src.mut_slice(start, end).mut_iter()).advance |(a, b)| { + util::swap(a, b); + } + cmp::min(self.len(), end-start) + } + #[inline] unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); @@ -2219,6 +1793,23 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { } } +/// Trait for ~[T] where T is Cloneable +pub trait MutableCloneableVector<T> { + /// Copies as many elements from `src` as it can into `self` + /// (the shorter of self.len() and src.len()). Returns the number of elements copied. + fn copy_from(self, &[T]) -> uint; +} + +impl<'self, T:Clone> MutableCloneableVector<T> for &'self mut [T] { + #[inline] + fn copy_from(self, src: &[T]) -> uint { + for self.mut_iter().zip(src.iter()).advance |(a, b)| { + *a = b.clone(); + } + cmp::min(self.len(), src.len()) + } +} + /** * Constructs a vector from an unsafe pointer to a buffer * @@ -2249,7 +1840,7 @@ pub mod raw { use ptr; use sys; use unstable::intrinsics; - use vec::{UnboxedVecRepr, as_const_buf, as_mut_buf, with_capacity}; + use vec::{UnboxedVecRepr, as_imm_buf, as_mut_buf, with_capacity}; use util; /// The internal representation of a (boxed) vector @@ -2299,15 +1890,6 @@ pub mod raw { /** see `to_ptr()` */ #[inline] - pub fn to_const_ptr<T>(v: &const [T]) -> *const T { - unsafe { - let repr: **SliceRepr = transmute(&v); - transmute(&((**repr).data)) - } - } - - /** see `to_ptr()` */ - #[inline] pub fn to_mut_ptr<T>(v: &mut [T]) -> *mut T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2345,8 +1927,8 @@ pub mod raw { * Unchecked vector indexing. */ #[inline] - pub unsafe fn get<T:Copy>(v: &const [T], i: uint) -> T { - as_const_buf(v, |p, _len| copy *ptr::const_offset(p, i)) + pub unsafe fn get<T:Copy>(v: &[T], i: uint) -> T { + as_imm_buf(v, |p, _len| copy *ptr::offset(p, i)) } /** @@ -2388,13 +1970,13 @@ pub mod raw { * may overlap. */ #[inline] - pub unsafe fn copy_memory<T>(dst: &mut [T], src: &const [T], + pub unsafe fn copy_memory<T>(dst: &mut [T], src: &[T], count: uint) { assert!(dst.len() >= count); assert!(src.len() >= count); do as_mut_buf(dst) |p_dst, _len_dst| { - do as_const_buf(src) |p_src, _len_src| { + do as_imm_buf(src) |p_src, _len_src| { ptr::copy_memory(p_dst, p_src, count) } } @@ -2407,6 +1989,22 @@ pub mod bytes { use uint; use vec::raw; use vec; + use ptr; + + /// A trait for operations on mutable operations on `[u8]` + pub trait MutableByteVector { + /// Sets all bytes of the receiver to the given value. + pub fn set_memory(self, value: u8); + } + + impl<'self> MutableByteVector for &'self mut [u8] { + #[inline] + fn set_memory(self, value: u8) { + do vec::as_mut_buf(self) |p, len| { + unsafe { ptr::set_memory(p, value, len) }; + } + } + } /// Bytewise string comparison pub fn memcmp(a: &~[u8], b: &~[u8]) -> int { @@ -2454,174 +2052,16 @@ pub mod bytes { * may overlap. */ #[inline] - pub fn copy_memory(dst: &mut [u8], src: &const [u8], count: uint) { + pub fn copy_memory(dst: &mut [u8], src: &[u8], count: uint) { // Bound checks are done at vec::raw::copy_memory. unsafe { vec::raw::copy_memory(dst, src, count) } } } -// ___________________________________________________________________________ -// ITERATION TRAIT METHODS - -impl<'self,A> old_iter::BaseIter<A> for &'self [A] { - #[inline] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { - each(*self, blk) - } - #[inline] - fn size_hint(&self) -> Option<uint> { Some(self.len()) } -} - -// FIXME(#4148): This should be redundant -impl<A> old_iter::BaseIter<A> for ~[A] { - #[inline] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { - each(*self, blk) - } - #[inline] - fn size_hint(&self) -> Option<uint> { Some(self.len()) } -} - -// FIXME(#4148): This should be redundant -impl<A> old_iter::BaseIter<A> for @[A] { - #[inline] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { - each(*self, blk) - } - #[inline] - fn size_hint(&self) -> Option<uint> { Some(self.len()) } -} - -impl<'self,A> old_iter::ExtendedIter<A> for &'self [A] { - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { - old_iter::eachi(self, blk) - } - pub fn all(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::all(self, blk) - } - pub fn any(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::any(self, blk) - } - pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { - old_iter::foldl(self, b0, blk) - } - pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> { - old_iter::position(self, f) - } - fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] { - old_iter::map_to_vec(self, op) - } - fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB) - -> ~[B] { - old_iter::flat_map_to_vec(self, op) - } -} - -// FIXME(#4148): This should be redundant -impl<A> old_iter::ExtendedIter<A> for ~[A] { - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { - old_iter::eachi(self, blk) - } - pub fn all(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::all(self, blk) - } - pub fn any(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::any(self, blk) - } - pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { - old_iter::foldl(self, b0, blk) - } - pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> { - old_iter::position(self, f) - } - fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] { - old_iter::map_to_vec(self, op) - } - fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB) - -> ~[B] { - old_iter::flat_map_to_vec(self, op) - } -} - -// FIXME(#4148): This should be redundant -impl<A> old_iter::ExtendedIter<A> for @[A] { - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { - old_iter::eachi(self, blk) - } - pub fn all(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::all(self, blk) - } - pub fn any(&self, blk: &fn(&A) -> bool) -> bool { - old_iter::any(self, blk) - } - pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { - old_iter::foldl(self, b0, blk) - } - pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> { - old_iter::position(self, f) - } - fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] { - old_iter::map_to_vec(self, op) - } - fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB) - -> ~[B] { - old_iter::flat_map_to_vec(self, op) - } -} - -impl<'self,A:Eq> old_iter::EqIter<A> for &'self [A] { - pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) } - pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) } -} - -// FIXME(#4148): This should be redundant -impl<A:Eq> old_iter::EqIter<A> for ~[A] { - pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) } - pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) } -} - -// FIXME(#4148): This should be redundant -impl<A:Eq> old_iter::EqIter<A> for @[A] { - pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) } - pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) } -} - -impl<'self,A:Copy> old_iter::CopyableIter<A> for &'self [A] { - fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] { - old_iter::filter_to_vec(self, pred) - } - fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) } - pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> { - old_iter::find(self, f) - } -} - -// FIXME(#4148): This should be redundant -impl<A:Copy> old_iter::CopyableIter<A> for ~[A] { - fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] { - old_iter::filter_to_vec(self, pred) - } - fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) } - pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> { - old_iter::find(self, f) - } -} - -// FIXME(#4148): This should be redundant -impl<A:Copy> old_iter::CopyableIter<A> for @[A] { - fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] { - old_iter::filter_to_vec(self, pred) - } - fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) } - pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> { - old_iter::find(self, f) - } -} - impl<A:Clone> Clone for ~[A] { #[inline] fn clone(&self) -> ~[A] { - self.map(|item| item.clone()) + self.iter().transform(|item| item.clone()).collect() } } @@ -2665,6 +2105,12 @@ macro_rules! iterator { } } } + + #[inline] + fn size_hint(&self) -> (Option<uint>, Option<uint>) { + let exact = Some(((self.end as uint) - (self.ptr as uint)) / size_of::<$elem>()); + (exact, exact) + } } } } @@ -2714,6 +2160,31 @@ impl<T> FromIter<T> for ~[T]{ } } +#[cfg(stage0)] +impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] { + pub fn from_iterator(iterator: &mut T) -> ~[A] { + let mut xs = ~[]; + for iterator.advance |x| { + xs.push(x); + } + xs + } +} + + +#[cfg(not(stage0))] +impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] { + pub fn from_iterator(iterator: &mut T) -> ~[A] { + let (lower, _) = iterator.size_hint(); + let mut xs = with_capacity(lower.get_or_zero()); + for iterator.advance |x| { + xs.push(x); + } + xs + } +} + + #[cfg(test)] mod tests { use option::{None, Option, Some}; @@ -2942,7 +2413,7 @@ mod tests { fn test_slice() { // Test fixed length vector. let vec_fixed = [1, 2, 3, 4]; - let v_a = slice(vec_fixed, 1u, vec_fixed.len()).to_vec(); + let v_a = vec_fixed.slice(1u, vec_fixed.len()).to_owned(); assert_eq!(v_a.len(), 3u); assert_eq!(v_a[0], 2); assert_eq!(v_a[1], 3); @@ -2950,14 +2421,14 @@ mod tests { // Test on stack. let vec_stack = &[1, 2, 3]; - let v_b = slice(vec_stack, 1u, 3u).to_vec(); + let v_b = vec_stack.slice(1u, 3u).to_owned(); assert_eq!(v_b.len(), 2u); assert_eq!(v_b[0], 2); assert_eq!(v_b[1], 3); // Test on managed heap. let vec_managed = @[1, 2, 3, 4, 5]; - let v_c = slice(vec_managed, 0u, 3u).to_vec(); + let v_c = vec_managed.slice(0u, 3u).to_owned(); assert_eq!(v_c.len(), 3u); assert_eq!(v_c[0], 1); assert_eq!(v_c[1], 2); @@ -2965,7 +2436,7 @@ mod tests { // Test on exchange heap. let vec_unique = ~[1, 2, 3, 4, 5, 6]; - let v_d = slice(vec_unique, 1u, 6u).to_vec(); + let v_d = vec_unique.slice(1u, 6u).to_owned(); assert_eq!(v_d.len(), 5u); assert_eq!(v_d[0], 2); assert_eq!(v_d[1], 3); @@ -3137,16 +2608,16 @@ mod tests { #[test] fn test_map() { // Test on-stack map. - let mut v = ~[1u, 2u, 3u]; - let mut w = map(v, square_ref); + let v = &[1u, 2u, 3u]; + let mut w = v.map(square_ref); assert_eq!(w.len(), 3u); assert_eq!(w[0], 1u); assert_eq!(w[1], 4u); assert_eq!(w[2], 9u); // Test on-heap map. - v = ~[1u, 2u, 3u, 4u, 5u]; - w = map(v, square_ref); + let v = ~[1u, 2u, 3u, 4u, 5u]; + w = v.map(square_ref); assert_eq!(w.len(), 5u); assert_eq!(w[0], 1u); assert_eq!(w[1], 4u); @@ -3156,17 +2627,6 @@ mod tests { } #[test] - fn test_map_zip() { - fn times(x: &int, y: &int) -> int { *x * *y } - let f = times; - let v0 = ~[1, 2, 3, 4, 5]; - let v1 = ~[5, 4, 3, 2, 1]; - let u = map_zip::<int, int, int>(v0, v1, f); - let mut i = 0; - while i < 5 { assert!(v0[i] * v1[i] == u[i]); i += 1; } - } - - #[test] fn test_filter_mapped() { // Test on-stack filter-map. let mut v = ~[1u, 2u, 3u]; @@ -3197,7 +2657,7 @@ mod tests { let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3]; let mix_dest: ~[int] = ~[1, 3, 0, 0]; assert!(filter_mapped(all_even, halve) == - map(all_even, halve_for_sure)); + all_even.map(halve_for_sure)); assert_eq!(filter_mapped(all_odd1, halve), ~[]); assert_eq!(filter_mapped(all_odd2, halve), ~[]); assert_eq!(filter_mapped(mix, halve), mix_dest); @@ -3235,7 +2695,7 @@ mod tests { let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3]; let mix_dest: ~[int] = ~[1, 3, 0, 0]; assert!(filter_map(all_even, halve) == - map(all_even0, halve_for_sure)); + all_even0.map(halve_for_sure)); assert_eq!(filter_map(all_odd1, halve), ~[]); assert_eq!(filter_map(all_odd2, halve), ~[]); assert_eq!(filter_map(mix, halve), mix_dest); @@ -3255,47 +2715,6 @@ mod tests { } #[test] - fn test_each_empty() { - for each::<int>([]) |_v| { - fail!(); // should never be executed - } - } - - #[test] - fn test_each_nonempty() { - let mut i = 0; - for each([1, 2, 3]) |v| { - i += *v; - } - assert_eq!(i, 6); - } - - #[test] - fn test_eachi() { - let mut i = 0; - for eachi([1, 2, 3]) |j, v| { - if i == 0 { assert!(*v == 1); } - assert_eq!(j + 1u, *v as uint); - i += *v; - } - assert_eq!(i, 6); - } - - #[test] - fn test_each_ret_len0() { - let a0 : [int, .. 0] = []; - assert_eq!(each(a0, |_p| fail!()), true); - } - - #[test] - fn test_each_ret_len1() { - let a1 = [17]; - assert_eq!(each(a1, |_p| true), true); - assert_eq!(each(a1, |_p| false), false); - } - - - #[test] fn test_each_permutation() { let mut results: ~[~[int]]; @@ -3337,218 +2756,68 @@ mod tests { #[test] fn test_position_elem() { - assert!(position_elem([], &1).is_none()); + assert!([].position_elem(&1).is_none()); let v1 = ~[1, 2, 3, 3, 2, 5]; - assert_eq!(position_elem(v1, &1), Some(0u)); - assert_eq!(position_elem(v1, &2), Some(1u)); - assert_eq!(position_elem(v1, &5), Some(5u)); - assert!(position_elem(v1, &4).is_none()); - } - - #[test] - fn test_position() { - fn less_than_three(i: &int) -> bool { *i < 3 } - fn is_eighteen(i: &int) -> bool { *i == 18 } - - assert!(position([], less_than_three).is_none()); - - let v1 = ~[5, 4, 3, 2, 1]; - assert_eq!(position(v1, less_than_three), Some(3u)); - assert!(position(v1, is_eighteen).is_none()); - } - - #[test] - fn test_position_between() { - assert!(position_between([], 0u, 0u, f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert!(position_between(v, 0u, 0u, f).is_none()); - assert!(position_between(v, 0u, 1u, f).is_none()); - assert_eq!(position_between(v, 0u, 2u, f), Some(1u)); - assert_eq!(position_between(v, 0u, 3u, f), Some(1u)); - assert_eq!(position_between(v, 0u, 4u, f), Some(1u)); - - assert!(position_between(v, 1u, 1u, f).is_none()); - assert_eq!(position_between(v, 1u, 2u, f), Some(1u)); - assert_eq!(position_between(v, 1u, 3u, f), Some(1u)); - assert_eq!(position_between(v, 1u, 4u, f), Some(1u)); - - assert!(position_between(v, 2u, 2u, f).is_none()); - assert!(position_between(v, 2u, 3u, f).is_none()); - assert_eq!(position_between(v, 2u, 4u, f), Some(3u)); - - assert!(position_between(v, 3u, 3u, f).is_none()); - assert_eq!(position_between(v, 3u, 4u, f), Some(3u)); - - assert!(position_between(v, 4u, 4u, f).is_none()); - } - - #[test] - fn test_find() { - assert!(find([], f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert_eq!(find(v, f), Some((1, 'b'))); - assert!(find(v, g).is_none()); - } - - #[test] - fn test_find_between() { - assert!(find_between([], 0u, 0u, f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert!(find_between(v, 0u, 0u, f).is_none()); - assert!(find_between(v, 0u, 1u, f).is_none()); - assert_eq!(find_between(v, 0u, 2u, f), Some((1, 'b'))); - assert_eq!(find_between(v, 0u, 3u, f), Some((1, 'b'))); - assert_eq!(find_between(v, 0u, 4u, f), Some((1, 'b'))); - - assert!(find_between(v, 1u, 1u, f).is_none()); - assert_eq!(find_between(v, 1u, 2u, f), Some((1, 'b'))); - assert_eq!(find_between(v, 1u, 3u, f), Some((1, 'b'))); - assert_eq!(find_between(v, 1u, 4u, f), Some((1, 'b'))); - - assert!(find_between(v, 2u, 2u, f).is_none()); - assert!(find_between(v, 2u, 3u, f).is_none()); - assert_eq!(find_between(v, 2u, 4u, f), Some((3, 'b'))); - - assert!(find_between(v, 3u, 3u, f).is_none()); - assert_eq!(find_between(v, 3u, 4u, f), Some((3, 'b'))); - - assert!(find_between(v, 4u, 4u, f).is_none()); + assert_eq!(v1.position_elem(&1), Some(0u)); + assert_eq!(v1.position_elem(&2), Some(1u)); + assert_eq!(v1.position_elem(&5), Some(5u)); + assert!(v1.position_elem(&4).is_none()); } #[test] fn test_rposition() { - assert!(find([], f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert_eq!(position(v, f), Some(1u)); - assert!(position(v, g).is_none()); - } - - #[test] - fn test_rposition_between() { - assert!(rposition_between([], 0u, 0u, f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert!(rposition_between(v, 0u, 0u, f).is_none()); - assert!(rposition_between(v, 0u, 1u, f).is_none()); - assert_eq!(rposition_between(v, 0u, 2u, f), Some(1u)); - assert_eq!(rposition_between(v, 0u, 3u, f), Some(1u)); - assert_eq!(rposition_between(v, 0u, 4u, f), Some(3u)); - - assert!(rposition_between(v, 1u, 1u, f).is_none()); - assert_eq!(rposition_between(v, 1u, 2u, f), Some(1u)); - assert_eq!(rposition_between(v, 1u, 3u, f), Some(1u)); - assert_eq!(rposition_between(v, 1u, 4u, f), Some(3u)); - - assert!(rposition_between(v, 2u, 2u, f).is_none()); - assert!(rposition_between(v, 2u, 3u, f).is_none()); - assert_eq!(rposition_between(v, 2u, 4u, f), Some(3u)); - - assert!(rposition_between(v, 3u, 3u, f).is_none()); - assert_eq!(rposition_between(v, 3u, 4u, f), Some(3u)); - - assert!(rposition_between(v, 4u, 4u, f).is_none()); - } - - #[test] - fn test_rfind() { - assert!(rfind([], f).is_none()); - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - assert_eq!(rfind(v, f), Some((3, 'b'))); - assert!(rfind(v, g).is_none()); - } - - #[test] - fn test_rfind_between() { - assert!(rfind_between([], 0u, 0u, f).is_none()); - - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert!(rfind_between(v, 0u, 0u, f).is_none()); - assert!(rfind_between(v, 0u, 1u, f).is_none()); - assert_eq!(rfind_between(v, 0u, 2u, f), Some((1, 'b'))); - assert_eq!(rfind_between(v, 0u, 3u, f), Some((1, 'b'))); - assert_eq!(rfind_between(v, 0u, 4u, f), Some((3, 'b'))); - - assert!(rfind_between(v, 1u, 1u, f).is_none()); - assert_eq!(rfind_between(v, 1u, 2u, f), Some((1, 'b'))); - assert_eq!(rfind_between(v, 1u, 3u, f), Some((1, 'b'))); - assert_eq!(rfind_between(v, 1u, 4u, f), Some((3, 'b'))); - - assert!(rfind_between(v, 2u, 2u, f).is_none()); - assert!(rfind_between(v, 2u, 3u, f).is_none()); - assert_eq!(rfind_between(v, 2u, 4u, f), Some((3, 'b'))); - - assert!(rfind_between(v, 3u, 3u, f).is_none()); - assert_eq!(rfind_between(v, 3u, 4u, f), Some((3, 'b'))); - - assert!(rfind_between(v, 4u, 4u, f).is_none()); + assert_eq!(v.rposition(f), Some(3u)); + assert!(v.rposition(g).is_none()); } #[test] fn test_bsearch_elem() { - assert_eq!(bsearch_elem([1,2,3,4,5], &5), Some(4)); - assert_eq!(bsearch_elem([1,2,3,4,5], &4), Some(3)); - assert_eq!(bsearch_elem([1,2,3,4,5], &3), Some(2)); - assert_eq!(bsearch_elem([1,2,3,4,5], &2), Some(1)); - assert_eq!(bsearch_elem([1,2,3,4,5], &1), Some(0)); + assert_eq!([1,2,3,4,5].bsearch_elem(&5), Some(4)); + assert_eq!([1,2,3,4,5].bsearch_elem(&4), Some(3)); + assert_eq!([1,2,3,4,5].bsearch_elem(&3), Some(2)); + assert_eq!([1,2,3,4,5].bsearch_elem(&2), Some(1)); + assert_eq!([1,2,3,4,5].bsearch_elem(&1), Some(0)); - assert_eq!(bsearch_elem([2,4,6,8,10], &1), None); - assert_eq!(bsearch_elem([2,4,6,8,10], &5), None); - assert_eq!(bsearch_elem([2,4,6,8,10], &4), Some(1)); - assert_eq!(bsearch_elem([2,4,6,8,10], &10), Some(4)); + assert_eq!([2,4,6,8,10].bsearch_elem(&1), None); + assert_eq!([2,4,6,8,10].bsearch_elem(&5), None); + assert_eq!([2,4,6,8,10].bsearch_elem(&4), Some(1)); + assert_eq!([2,4,6,8,10].bsearch_elem(&10), Some(4)); - assert_eq!(bsearch_elem([2,4,6,8], &1), None); - assert_eq!(bsearch_elem([2,4,6,8], &5), None); - assert_eq!(bsearch_elem([2,4,6,8], &4), Some(1)); - assert_eq!(bsearch_elem([2,4,6,8], &8), Some(3)); + assert_eq!([2,4,6,8].bsearch_elem(&1), None); + assert_eq!([2,4,6,8].bsearch_elem(&5), None); + assert_eq!([2,4,6,8].bsearch_elem(&4), Some(1)); + assert_eq!([2,4,6,8].bsearch_elem(&8), Some(3)); - assert_eq!(bsearch_elem([2,4,6], &1), None); - assert_eq!(bsearch_elem([2,4,6], &5), None); - assert_eq!(bsearch_elem([2,4,6], &4), Some(1)); - assert_eq!(bsearch_elem([2,4,6], &6), Some(2)); + assert_eq!([2,4,6].bsearch_elem(&1), None); + assert_eq!([2,4,6].bsearch_elem(&5), None); + assert_eq!([2,4,6].bsearch_elem(&4), Some(1)); + assert_eq!([2,4,6].bsearch_elem(&6), Some(2)); - assert_eq!(bsearch_elem([2,4], &1), None); - assert_eq!(bsearch_elem([2,4], &5), None); - assert_eq!(bsearch_elem([2,4], &2), Some(0)); - assert_eq!(bsearch_elem([2,4], &4), Some(1)); + assert_eq!([2,4].bsearch_elem(&1), None); + assert_eq!([2,4].bsearch_elem(&5), None); + assert_eq!([2,4].bsearch_elem(&2), Some(0)); + assert_eq!([2,4].bsearch_elem(&4), Some(1)); - assert_eq!(bsearch_elem([2], &1), None); - assert_eq!(bsearch_elem([2], &5), None); - assert_eq!(bsearch_elem([2], &2), Some(0)); + assert_eq!([2].bsearch_elem(&1), None); + assert_eq!([2].bsearch_elem(&5), None); + assert_eq!([2].bsearch_elem(&2), Some(0)); - assert_eq!(bsearch_elem([], &1), None); - assert_eq!(bsearch_elem([], &5), None); + assert_eq!([].bsearch_elem(&1), None); + assert_eq!([].bsearch_elem(&5), None); - assert!(bsearch_elem([1,1,1,1,1], &1) != None); - assert!(bsearch_elem([1,1,1,1,2], &1) != None); - assert!(bsearch_elem([1,1,1,2,2], &1) != None); - assert!(bsearch_elem([1,1,2,2,2], &1) != None); - assert_eq!(bsearch_elem([1,2,2,2,2], &1), Some(0)); + assert!([1,1,1,1,1].bsearch_elem(&1) != None); + assert!([1,1,1,1,2].bsearch_elem(&1) != None); + assert!([1,1,1,2,2].bsearch_elem(&1) != None); + assert!([1,1,2,2,2].bsearch_elem(&1) != None); + assert_eq!([1,2,2,2,2].bsearch_elem(&1), Some(0)); - assert_eq!(bsearch_elem([1,2,3,4,5], &6), None); - assert_eq!(bsearch_elem([1,2,3,4,5], &0), None); + assert_eq!([1,2,3,4,5].bsearch_elem(&6), None); + assert_eq!([1,2,3,4,5].bsearch_elem(&0), None); } #[test] @@ -3556,7 +2825,7 @@ mod tests { let mut v: ~[int] = ~[10, 20]; assert_eq!(v[0], 10); assert_eq!(v[1], 20); - reverse(v); + v.reverse(); assert_eq!(v[0], 20); assert_eq!(v[1], 10); let v2 = reversed::<int>([10, 20]); @@ -3569,7 +2838,7 @@ mod tests { let v4 = reversed::<int>([]); assert_eq!(v4, ~[]); let mut v3: ~[int] = ~[]; - reverse::<int>(v3); + v3.reverse(); } #[test] @@ -3625,11 +2894,10 @@ mod tests { #[test] fn test_partition() { - // FIXME (#4355 maybe): using v.partition here crashes - assert_eq!(partition(~[], |x: &int| *x < 3), (~[], ~[])); - assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 4), (~[1, 2, 3], ~[])); - assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 2), (~[1], ~[2, 3])); - assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 0), (~[], ~[1, 2, 3])); + assert_eq!((~[]).partition(|x: &int| *x < 3), (~[], ~[])); + assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 4), (~[1, 2, 3], ~[])); + assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 2), (~[1], ~[2, 3])); + assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 0), (~[], ~[1, 2, 3])); } #[test] @@ -3749,11 +3017,11 @@ mod tests { #[test] fn test_capacity() { let mut v = ~[0u64]; - reserve(&mut v, 10u); - assert_eq!(capacity(&v), 10u); + v.reserve(10u); + assert_eq!(v.capacity(), 10u); let mut v = ~[0u32]; - reserve(&mut v, 10u); - assert_eq!(capacity(&v), 10u); + v.reserve(10u); + assert_eq!(v.capacity(), 10u); } #[test] @@ -3959,7 +3227,7 @@ mod tests { fn test_map_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do map(v) |_elt| { + do v.map |_elt| { if i == 2 { fail!() } @@ -3986,41 +3254,10 @@ mod tests { #[test] #[ignore(windows)] #[should_fail] - fn test_mapi_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do mapi(v) |_i, _elt| { - if i == 2 { - fail!() - } - i += 0; - ~[(~0, @0)] - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] fn test_flat_map_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do map(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - ~[(~0, @0)] - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_map_zip_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do map_zip(v, v) |_elt1, _elt2| { + do flat_map(v) |_elt| { if i == 2 { fail!() } @@ -4064,71 +3301,10 @@ mod tests { #[test] #[ignore(windows)] #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_find_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do find(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - fn test_position_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do position(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] fn test_rposition_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do rposition(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - fn test_each_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do each(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - fn test_eachi_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do eachi(v) |_i, _elt| { + do v.rposition |_elt| { if i == 2 { fail!() } @@ -4163,16 +3339,6 @@ mod tests { } #[test] - #[ignore(windows)] - #[should_fail] - fn test_as_const_buf_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - do as_const_buf(v) |_buf, _i| { - fail!() - } - } - - #[test] #[ignore(cfg(windows))] #[should_fail] fn test_as_mut_buf_fail() { @@ -4206,13 +3372,19 @@ mod tests { fn test_iterator() { use iterator::*; let xs = [1, 2, 5, 10, 11]; - let ys = [1, 2, 5, 10, 11, 19]; let mut it = xs.iter(); - let mut i = 0; - for it.advance |&x| { - assert_eq!(x, ys[i]); - i += 1; - } + assert_eq!(it.size_hint(), (Some(5), Some(5))); + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.size_hint(), (Some(4), Some(4))); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.size_hint(), (Some(3), Some(3))); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.size_hint(), (Some(2), Some(2))); + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.size_hint(), (Some(1), Some(1))); + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.size_hint(), (Some(0), Some(0))); + assert!(it.next().is_none()); } #[test] @@ -4250,9 +3422,41 @@ mod tests { } #[test] + fn test_move_from() { + let mut a = [1,2,3,4,5]; + let b = ~[6,7,8]; + assert_eq!(a.move_from(b, 0, 3), 3); + assert_eq!(a, [6,7,8,4,5]); + let mut a = [7,2,8,1]; + let b = ~[3,1,4,1,5,9]; + assert_eq!(a.move_from(b, 0, 6), 4); + assert_eq!(a, [3,1,4,1]); + let mut a = [1,2,3,4]; + let b = ~[5,6,7,8,9,0]; + assert_eq!(a.move_from(b, 2, 3), 1); + assert_eq!(a, [7,2,3,4]); + let mut a = [1,2,3,4,5]; + let b = ~[5,6,7,8,9,0]; + assert_eq!(a.mut_slice(2,4).move_from(b,1,6), 2); + assert_eq!(a, [1,2,6,7,5]); + } + + #[test] + fn test_copy_from() { + let mut a = [1,2,3,4,5]; + let b = [6,7,8]; + assert_eq!(a.copy_from(b), 3); + assert_eq!(a, [6,7,8,4,5]); + let mut c = [7,2,8,1]; + let d = [3,1,4,1,5,9]; + assert_eq!(c.copy_from(d), 4); + assert_eq!(c, [3,1,4,1]); + } + + #[test] fn test_reverse_part() { let mut values = [1,2,3,4,5]; - reverse_part(values,1,4); + values.mut_slice(1, 4).reverse(); assert_eq!(values, [1,4,3,2,5]); } @@ -4300,15 +3504,25 @@ mod tests { fn test_vec_zero() { use num::Zero; macro_rules! t ( - ($ty:ty) => { + ($ty:ty) => {{ let v: $ty = Zero::zero(); assert!(v.is_empty()); assert!(v.is_zero()); - } + }} ); t!(&[int]); t!(@[int]); t!(~[int]); } + + #[test] + fn test_bytes_set_memory() { + use vec::bytes::MutableByteVector; + let mut values = [1u8,2,3,4,5]; + values.mut_slice(0,5).set_memory(0xAB); + assert_eq!(values, [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); + values.mut_slice(2,4).set_memory(0xFF); + assert_eq!(values, [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); + } } |
