Merge remote-tracking branch 'mozilla/master'
Conflicts: src/libextra/test.rs src/libstd/at_vec.rs src/libstd/cleanup.rs src/libstd/rt/comm.rs src/libstd/rt/global_heap.rs src/libstd/task/spawn.rs src/libstd/unstable/lang.rs src/libstd/vec.rs src/rt/rustrt.def.in src/test/run-pass/extern-pub.rs
This commit is contained in:
commit
1098d6980b
765 changed files with 23500 additions and 17316 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */ }
|
||||
|
|
|
|||
|
|
@ -40,12 +40,13 @@ with destructors.
|
|||
use cast;
|
||||
use container::{Map, Set};
|
||||
use io;
|
||||
use libc::{size_t, uintptr_t};
|
||||
use libc::{uintptr_t};
|
||||
use option::{None, Option, Some};
|
||||
use ptr;
|
||||
use hashmap::HashSet;
|
||||
use stackwalk::walk_stack;
|
||||
use sys;
|
||||
use unstable::intrinsics::{TyDesc};
|
||||
|
||||
pub use stackwalk::Word;
|
||||
|
||||
|
|
@ -58,17 +59,11 @@ pub struct StackSegment {
|
|||
}
|
||||
|
||||
pub mod rustrt {
|
||||
use libc::size_t;
|
||||
use stackwalk::Word;
|
||||
use super::StackSegment;
|
||||
|
||||
#[link_name = "rustrt"]
|
||||
pub extern {
|
||||
#[rust_stack]
|
||||
pub unsafe fn rust_call_tydesc_glue(root: *Word,
|
||||
tydesc: *Word,
|
||||
field: size_t);
|
||||
|
||||
#[rust_stack]
|
||||
pub unsafe fn rust_gc_metadata() -> *Word;
|
||||
|
||||
|
|
@ -125,7 +120,7 @@ unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
|
|||
return None;
|
||||
}
|
||||
|
||||
type Visitor<'self> = &'self fn(root: **Word, tydesc: *Word) -> bool;
|
||||
type Visitor<'self> = &'self fn(root: **Word, tydesc: *TyDesc) -> bool;
|
||||
|
||||
// Walks the list of roots for the given safe point, and calls visitor
|
||||
// on each root.
|
||||
|
|
@ -139,7 +134,7 @@ unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
|
|||
let stack_roots: *u32 = bump(sp_meta, 2);
|
||||
let reg_roots: *u8 = bump(stack_roots, num_stack_roots);
|
||||
let addrspaces: *Word = align_to_pointer(bump(reg_roots, num_reg_roots));
|
||||
let tydescs: ***Word = bump(addrspaces, num_stack_roots);
|
||||
let tydescs: ***TyDesc = bump(addrspaces, num_stack_roots);
|
||||
|
||||
// Stack roots
|
||||
let mut sri = 0;
|
||||
|
|
@ -321,6 +316,19 @@ fn expect_sentinel() -> bool { true }
|
|||
#[cfg(nogc)]
|
||||
fn expect_sentinel() -> bool { false }
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
|
||||
// This function should be inlined when stage0 is gone
|
||||
((*tydesc).drop_glue)(data);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
|
||||
((*tydesc).drop_glue)(0 as **TyDesc, data);
|
||||
}
|
||||
|
||||
// Entry point for GC-based cleanup. Walks stack looking for exchange
|
||||
// heap and stack allocations requiring drop, and runs all
|
||||
// destructors.
|
||||
|
|
@ -364,7 +372,7 @@ pub fn cleanup_stack_for_failure() {
|
|||
// FIXME #4420: Destroy this box
|
||||
// FIXME #4330: Destroy this box
|
||||
} else {
|
||||
rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
|
||||
call_drop_glue(tydesc, *root as *i8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -18,14 +18,13 @@
|
|||
use container::{Container, Mutable, Map, Set};
|
||||
use cmp::{Eq, Equiv};
|
||||
use hash::Hash;
|
||||
use old_iter::BaseIter;
|
||||
use old_iter;
|
||||
use iterator::{IteratorUtil};
|
||||
use iterator::{Iterator, IteratorUtil};
|
||||
use option::{None, Option, Some};
|
||||
use rand::RngUtil;
|
||||
use rand;
|
||||
use uint;
|
||||
use vec;
|
||||
use vec::{ImmutableVector, MutableVector};
|
||||
use kinds::Copy;
|
||||
use util::{replace, unreachable};
|
||||
|
||||
|
|
@ -283,10 +282,10 @@ impl<K:Hash + Eq,V> HashMap<K, V> {
|
|||
|
||||
impl<K:Hash + Eq,V> Container for HashMap<K, V> {
|
||||
/// Return the number of elements in the map
|
||||
fn len(&const self) -> uint { self.size }
|
||||
fn len(&self) -> uint { self.size }
|
||||
|
||||
/// Return true if the map contains no elements
|
||||
fn is_empty(&const self) -> bool { self.len() == 0 }
|
||||
fn is_empty(&self) -> bool { self.len() == 0 }
|
||||
}
|
||||
|
||||
impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
|
||||
|
|
@ -308,41 +307,6 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Visit all key-value pairs
|
||||
fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
|
||||
for self.buckets.each |bucket| {
|
||||
for bucket.iter().advance |pair| {
|
||||
if !blk(&pair.key, &pair.value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Visit all keys
|
||||
fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
|
||||
self.each(|k, _| blk(k))
|
||||
}
|
||||
|
||||
/// Visit all values
|
||||
fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
|
||||
self.each(|_, v| blk(v))
|
||||
}
|
||||
|
||||
/// Iterate over the map and mutate the contained values
|
||||
fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
|
||||
for uint::range(0, self.buckets.len()) |i| {
|
||||
match self.buckets[i] {
|
||||
Some(Bucket{key: ref key, value: ref mut value, _}) => {
|
||||
if !blk(key, value) { return false; }
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Return a reference to the value corresponding to the key
|
||||
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
|
||||
match self.bucket_for_key(k) {
|
||||
|
|
@ -523,6 +487,42 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
|
|||
TableFull | FoundHole(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Visit all keys
|
||||
pub fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
|
||||
self.iter().advance(|(k, _)| blk(k))
|
||||
}
|
||||
|
||||
/// Visit all values
|
||||
pub fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
|
||||
self.iter().advance(|(_, v)| blk(v))
|
||||
}
|
||||
|
||||
/// Iterate over the map and mutate the contained values
|
||||
pub fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
|
||||
for uint::range(0, self.buckets.len()) |i| {
|
||||
match self.buckets[i] {
|
||||
Some(Bucket{key: ref key, value: ref mut value, _}) => {
|
||||
if !blk(key, value) { return false; }
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// An iterator visiting all key-value pairs in arbitrary order.
|
||||
/// Iterator element type is (&'a K, &'a V).
|
||||
pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
|
||||
HashMapIterator { iter: self.buckets.iter() }
|
||||
}
|
||||
|
||||
/// An iterator visiting all key-value pairs in arbitrary order,
|
||||
/// with mutable references to the values.
|
||||
/// Iterator element type is (&'a K, &'a mut V).
|
||||
pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
|
||||
HashMapMutIterator { iter: self.buckets.mut_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
|
||||
|
|
@ -541,7 +541,7 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
|
|||
fn eq(&self, other: &HashMap<K, V>) -> bool {
|
||||
if self.len() != other.len() { return false; }
|
||||
|
||||
for self.each |key, value| {
|
||||
for self.iter().advance |(key, value)| {
|
||||
match other.find(key) {
|
||||
None => return false,
|
||||
Some(v) => if value != v { return false },
|
||||
|
|
@ -554,6 +554,61 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
|
|||
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
/// HashMap iterator
|
||||
pub struct HashMapIterator<'self, K, V> {
|
||||
priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
|
||||
}
|
||||
|
||||
/// HashMap mutable values iterator
|
||||
pub struct HashMapMutIterator<'self, K, V> {
|
||||
priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
|
||||
}
|
||||
|
||||
/// HashSet iterator
|
||||
pub struct HashSetIterator<'self, K> {
|
||||
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
|
||||
}
|
||||
|
||||
impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(&'self K, &'self V)> {
|
||||
for self.iter.advance |elt| {
|
||||
match elt {
|
||||
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
|
||||
&None => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'self, K, V> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
|
||||
for self.iter.advance |elt| {
|
||||
match elt {
|
||||
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
|
||||
&None => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'self K> {
|
||||
for self.iter.advance |elt| {
|
||||
match elt {
|
||||
&Some(ref bucket) => return Some(&bucket.key),
|
||||
&None => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An implementation of a hash set using the underlying representation of a
|
||||
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
|
||||
/// requires that the elements implement the `Eq` and `Hash` traits.
|
||||
|
|
@ -561,12 +616,6 @@ pub struct HashSet<T> {
|
|||
priv map: HashMap<T, ()>
|
||||
}
|
||||
|
||||
impl<T:Hash + Eq> BaseIter<T> for HashSet<T> {
|
||||
/// Visit all values in order
|
||||
fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) }
|
||||
fn size_hint(&self) -> Option<uint> { Some(self.len()) }
|
||||
}
|
||||
|
||||
impl<T:Hash + Eq> Eq for HashSet<T> {
|
||||
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
|
||||
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
|
||||
|
|
@ -574,10 +623,10 @@ impl<T:Hash + Eq> Eq for HashSet<T> {
|
|||
|
||||
impl<T:Hash + Eq> Container for HashSet<T> {
|
||||
/// Return the number of elements in the set
|
||||
fn len(&const self) -> uint { self.map.len() }
|
||||
fn len(&self) -> uint { self.map.len() }
|
||||
|
||||
/// Return true if the set contains no elements
|
||||
fn is_empty(&const self) -> bool { self.map.is_empty() }
|
||||
fn is_empty(&self) -> bool { self.map.is_empty() }
|
||||
}
|
||||
|
||||
impl<T:Hash + Eq> Mutable for HashSet<T> {
|
||||
|
|
@ -600,12 +649,12 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
|||
/// Return true if the set has no elements in common with `other`.
|
||||
/// This is equivalent to checking for an empty intersection.
|
||||
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
|
||||
old_iter::all(self, |v| !other.contains(v))
|
||||
self.iter().all(|v| !other.contains(v))
|
||||
}
|
||||
|
||||
/// Return true if the set is a subset of another
|
||||
fn is_subset(&self, other: &HashSet<T>) -> bool {
|
||||
old_iter::all(self, |v| other.contains(v))
|
||||
self.iter().all(|v| other.contains(v))
|
||||
}
|
||||
|
||||
/// Return true if the set is a superset of another
|
||||
|
|
@ -615,24 +664,25 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
|||
|
||||
/// Visit the values representing the difference
|
||||
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||
self.each(|v| other.contains(v) || f(v))
|
||||
self.iter().advance(|v| other.contains(v) || f(v))
|
||||
}
|
||||
|
||||
/// Visit the values representing the symmetric difference
|
||||
fn symmetric_difference(&self,
|
||||
other: &HashSet<T>,
|
||||
f: &fn(&T) -> bool) -> bool {
|
||||
self.difference(other, f) && other.difference(self, f)
|
||||
self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
|
||||
}
|
||||
|
||||
/// Visit the values representing the intersection
|
||||
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||
self.each(|v| !other.contains(v) || f(v))
|
||||
self.iter().advance(|v| !other.contains(v) || f(v))
|
||||
}
|
||||
|
||||
/// Visit the values representing the union
|
||||
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||
self.each(f) && other.each(|v| self.contains(v) || f(v))
|
||||
self.iter().advance(|t| f(t)) &&
|
||||
other.iter().advance(|v| self.contains(v) || f(v))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -663,6 +713,12 @@ impl<T:Hash + Eq> HashSet<T> {
|
|||
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
|
||||
self.map.contains_key_equiv(value)
|
||||
}
|
||||
|
||||
/// An iterator visiting all elements in arbitrary order.
|
||||
/// Iterator element type is &'a T.
|
||||
pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
|
||||
HashSetIterator { iter: self.map.buckets.iter() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -807,7 +863,7 @@ mod test_map {
|
|||
assert!(m.insert(i, i*2));
|
||||
}
|
||||
let mut observed = 0;
|
||||
for m.each |k, v| {
|
||||
for m.iter().advance |(k, v)| {
|
||||
assert_eq!(*v, *k * 2);
|
||||
observed |= (1 << *k);
|
||||
}
|
||||
|
|
@ -883,7 +939,8 @@ mod test_map {
|
|||
mod test_set {
|
||||
use super::*;
|
||||
use container::{Container, Map, Set};
|
||||
use vec;
|
||||
use vec::ImmutableEqVector;
|
||||
use uint;
|
||||
|
||||
#[test]
|
||||
fn test_disjoint() {
|
||||
|
|
@ -936,6 +993,19 @@ mod test_set {
|
|||
assert!(b.is_superset(&a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterate() {
|
||||
let mut a = HashSet::new();
|
||||
for uint::range(0, 32) |i| {
|
||||
assert!(a.insert(i));
|
||||
}
|
||||
let mut observed = 0;
|
||||
for a.iter().advance |k| {
|
||||
observed |= (1 << *k);
|
||||
}
|
||||
assert_eq!(observed, 0xFFFF_FFFF);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersection() {
|
||||
let mut a = HashSet::new();
|
||||
|
|
@ -960,7 +1030,7 @@ mod test_set {
|
|||
let mut i = 0;
|
||||
let expected = [3, 5, 11, 77];
|
||||
for a.intersection(&b) |x| {
|
||||
assert!(vec::contains(expected, x));
|
||||
assert!(expected.contains(x));
|
||||
i += 1
|
||||
}
|
||||
assert_eq!(i, expected.len());
|
||||
|
|
@ -983,7 +1053,7 @@ mod test_set {
|
|||
let mut i = 0;
|
||||
let expected = [1, 5, 11];
|
||||
for a.difference(&b) |x| {
|
||||
assert!(vec::contains(expected, x));
|
||||
assert!(expected.contains(x));
|
||||
i += 1
|
||||
}
|
||||
assert_eq!(i, expected.len());
|
||||
|
|
@ -1009,7 +1079,7 @@ mod test_set {
|
|||
let mut i = 0;
|
||||
let expected = [-2, 1, 5, 11, 14, 22];
|
||||
for a.symmetric_difference(&b) |x| {
|
||||
assert!(vec::contains(expected, x));
|
||||
assert!(expected.contains(x));
|
||||
i += 1
|
||||
}
|
||||
assert_eq!(i, expected.len());
|
||||
|
|
@ -1039,7 +1109,7 @@ mod test_set {
|
|||
let mut i = 0;
|
||||
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
|
||||
for a.union(&b) |x| {
|
||||
assert!(vec::contains(expected, x));
|
||||
assert!(expected.contains(x));
|
||||
i += 1
|
||||
}
|
||||
assert_eq!(i, expected.len());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,20 +17,33 @@ implementing the `Iterator` trait.
|
|||
|
||||
*/
|
||||
|
||||
#[allow(default_methods)]; // solid enough for the use case here
|
||||
|
||||
use cmp;
|
||||
use iter::{FromIter, Times};
|
||||
use iter::Times;
|
||||
use num::{Zero, One};
|
||||
use option::{Option, Some, None};
|
||||
use ops::{Add, Mul};
|
||||
use cmp::Ord;
|
||||
use clone::Clone;
|
||||
|
||||
/// Conversion from an `Iterator`
|
||||
pub trait FromIterator<A, T: Iterator<A>> {
|
||||
/// Build a container with elements from an external iterator.
|
||||
pub fn from_iterator(iterator: &mut T) -> Self;
|
||||
}
|
||||
|
||||
/// An interface for dealing with "external iterators". These types of iterators
|
||||
/// can be resumed at any time as all state is stored internally as opposed to
|
||||
/// being located on the call stack.
|
||||
pub trait Iterator<A> {
|
||||
/// Advance the iterator and return the next value. Return `None` when the end is reached.
|
||||
fn next(&mut self) -> Option<A>;
|
||||
|
||||
/// Return a lower bound and upper bound on the remaining length of the iterator.
|
||||
///
|
||||
/// The common use case for the estimate is pre-allocating space to store the results.
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
|
||||
}
|
||||
|
||||
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
|
||||
|
|
@ -72,8 +85,7 @@ pub trait IteratorUtil<A> {
|
|||
|
||||
// FIXME: #5898: should be called map
|
||||
/// Creates a new iterator which will apply the specified function to each
|
||||
/// element returned by the first, yielding the mapped element instead. This
|
||||
/// similar to the `vec::map` function.
|
||||
/// element returned by the first, yielding the mapped element instead.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
|
@ -212,6 +224,26 @@ pub trait IteratorUtil<A> {
|
|||
fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
|
||||
-> ScanIterator<'r, A, B, Self, St>;
|
||||
|
||||
/// Creates an iterator that maps each element to an iterator,
|
||||
/// and yields the elements of the produced iterators
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let xs = [2u, 3];
|
||||
/// let ys = [0u, 1, 0, 1, 2];
|
||||
/// let mut it = xs.iter().flat_map_(|&x| Counter::new(0u, 1).take_(x));
|
||||
/// // Check that `it` has the same elements as `ys`
|
||||
/// let mut i = 0;
|
||||
/// for it.advance |x: uint| {
|
||||
/// assert_eq!(x, ys[i]);
|
||||
/// i += 1;
|
||||
/// }
|
||||
/// ~~~
|
||||
// FIXME: #5898: should be called `flat_map`
|
||||
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
|
||||
-> FlatMapIterator<'r, A, B, Self, U>;
|
||||
|
||||
/// An adaptation of an external iterator to the for-loop protocol of rust.
|
||||
///
|
||||
/// # Example
|
||||
|
|
@ -226,7 +258,7 @@ pub trait IteratorUtil<A> {
|
|||
fn advance(&mut self, f: &fn(A) -> bool) -> bool;
|
||||
|
||||
/// Loops through the entire iterator, collecting all of the elements into
|
||||
/// a container implementing `FromIter`.
|
||||
/// a container implementing `FromIterator`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
|
@ -235,7 +267,7 @@ pub trait IteratorUtil<A> {
|
|||
/// let b: ~[int] = a.iter().transform(|&x| x).collect();
|
||||
/// assert!(a == b);
|
||||
/// ~~~
|
||||
fn collect<B: FromIter<A>>(&mut self) -> B;
|
||||
fn collect<B: FromIterator<A, Self>>(&mut self) -> B;
|
||||
|
||||
/// Loops through `n` iterations, returning the `n`th element of the
|
||||
/// iterator.
|
||||
|
|
@ -273,6 +305,7 @@ pub trait IteratorUtil<A> {
|
|||
/// ~~~
|
||||
fn fold<B>(&mut self, start: B, f: &fn(B, A) -> B) -> B;
|
||||
|
||||
// FIXME: #5898: should be called len
|
||||
/// Counts the number of elements in this iterator.
|
||||
///
|
||||
/// # Example
|
||||
|
|
@ -280,10 +313,10 @@ pub trait IteratorUtil<A> {
|
|||
/// ~~~ {.rust}
|
||||
/// let a = [1, 2, 3, 4, 5];
|
||||
/// let mut it = a.iter();
|
||||
/// assert!(it.count() == 5);
|
||||
/// assert!(it.count() == 0);
|
||||
/// assert!(it.len_() == 5);
|
||||
/// assert!(it.len_() == 0);
|
||||
/// ~~~
|
||||
fn count(&mut self) -> uint;
|
||||
fn len_(&mut self) -> uint;
|
||||
|
||||
/// Tests whether the predicate holds true for all elements in the iterator.
|
||||
///
|
||||
|
|
@ -314,6 +347,29 @@ pub trait IteratorUtil<A> {
|
|||
|
||||
/// Return the index of the first element satisfying the specified predicate
|
||||
fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
|
||||
|
||||
/// Count the number of elements satisfying the specified predicate
|
||||
fn count(&mut self, predicate: &fn(A) -> bool) -> uint;
|
||||
|
||||
/// Return the element that gives the maximum value from the specfied function
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let xs = [-3, 0, 1, 5, -10];
|
||||
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
|
||||
/// ~~~
|
||||
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
|
||||
|
||||
/// Return the element that gives the minimum value from the specfied function
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let xs = [-3, 0, 1, 5, -10];
|
||||
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
|
||||
/// ~~~
|
||||
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
|
||||
}
|
||||
|
||||
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
|
||||
|
|
@ -379,6 +435,12 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
|
|||
ScanIterator{iter: self, f: f, state: initial_state}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
|
||||
-> FlatMapIterator<'r, A, B, T, U> {
|
||||
FlatMapIterator{iter: self, f: f, subiter: None }
|
||||
}
|
||||
|
||||
/// A shim implementing the `for` loop iteration protocol for iterator objects
|
||||
#[inline]
|
||||
fn advance(&mut self, f: &fn(A) -> bool) -> bool {
|
||||
|
|
@ -393,8 +455,8 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn collect<B: FromIter<A>>(&mut self) -> B {
|
||||
FromIter::from_iter::<A, B>(|f| self.advance(f))
|
||||
fn collect<B: FromIterator<A, T>>(&mut self) -> B {
|
||||
FromIterator::from_iterator(self)
|
||||
}
|
||||
|
||||
/// Return the `n`th item yielded by an iterator.
|
||||
|
|
@ -432,7 +494,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
|
|||
|
||||
/// Count the number of items yielded by an iterator
|
||||
#[inline]
|
||||
fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
|
||||
fn len_(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
|
||||
|
||||
#[inline]
|
||||
fn all(&mut self, f: &fn(A) -> bool) -> bool {
|
||||
|
|
@ -467,6 +529,45 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(&mut self, predicate: &fn(A) -> bool) -> uint {
|
||||
let mut i = 0;
|
||||
for self.advance |x| {
|
||||
if predicate(x) { i += 1 }
|
||||
}
|
||||
i
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
|
||||
self.fold(None, |max: Option<(A, B)>, x| {
|
||||
let x_val = f(&x);
|
||||
match max {
|
||||
None => Some((x, x_val)),
|
||||
Some((y, y_val)) => if x_val > y_val {
|
||||
Some((x, x_val))
|
||||
} else {
|
||||
Some((y, y_val))
|
||||
}
|
||||
}
|
||||
}).map_consume(|(x, _)| x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
|
||||
self.fold(None, |min: Option<(A, B)>, x| {
|
||||
let x_val = f(&x);
|
||||
match min {
|
||||
None => Some((x, x_val)),
|
||||
Some((y, y_val)) => if x_val < y_val {
|
||||
Some((x, x_val))
|
||||
} else {
|
||||
Some((y, y_val))
|
||||
}
|
||||
}
|
||||
}).map_consume(|(x, _)| x)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for iterators over elements which can be added together
|
||||
|
|
@ -581,6 +682,26 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
|
|||
self.b.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = match (a_lower, b_lower) {
|
||||
(Some(x), Some(y)) => Some(x + y),
|
||||
(Some(x), None) => Some(x),
|
||||
(None, Some(y)) => Some(y),
|
||||
(None, None) => None
|
||||
};
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => Some(x + y),
|
||||
_ => None
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which iterates two other iterators simultaneously
|
||||
|
|
@ -614,6 +735,11 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
|
|||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which filters the elements of `iter` with `predicate`
|
||||
|
|
@ -634,6 +760,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(None, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which uses `f` to both filter and map elements from `iter`
|
||||
|
|
@ -653,6 +785,12 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(None, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which yields the current count and the element during iteration
|
||||
|
|
@ -805,6 +943,34 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
|
|||
}
|
||||
}
|
||||
|
||||
/// An iterator that maps each element to an iterator,
|
||||
/// and yields the elements of the produced iterators
|
||||
///
|
||||
// FIXME #6967: Dummy B parameter to get around type inference bug
|
||||
pub struct FlatMapIterator<'self, A, B, T, U> {
|
||||
priv iter: T,
|
||||
priv f: &'self fn(A) -> U,
|
||||
priv subiter: Option<U>,
|
||||
}
|
||||
|
||||
impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
|
||||
FlatMapIterator<'self, A, B, T, U> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
loop {
|
||||
for self.subiter.mut_iter().advance |inner| {
|
||||
for inner.advance |x| {
|
||||
return Some(x)
|
||||
}
|
||||
}
|
||||
match self.iter.next().map_consume(|x| (self.f)(x)) {
|
||||
None => return None,
|
||||
next => self.subiter = next,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which just modifies the contained state throughout iteration.
|
||||
pub struct UnfoldrIterator<'self, A, St> {
|
||||
priv f: &'self fn(&mut St) -> Option<A>,
|
||||
|
|
@ -816,7 +982,7 @@ impl<'self, A, St> UnfoldrIterator<'self, A, St> {
|
|||
/// Creates a new iterator with the specified closure as the "iterator
|
||||
/// function" and an initial state to eventually pass to the iterator
|
||||
#[inline]
|
||||
pub fn new<'a>(f: &'a fn(&mut St) -> Option<A>, initial_state: St)
|
||||
pub fn new<'a>(initial_state: St, f: &'a fn(&mut St) -> Option<A>)
|
||||
-> UnfoldrIterator<'a, A, St> {
|
||||
UnfoldrIterator {
|
||||
f: f,
|
||||
|
|
@ -863,13 +1029,12 @@ mod tests {
|
|||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
use iter;
|
||||
use uint;
|
||||
|
||||
#[test]
|
||||
fn test_counter_from_iter() {
|
||||
let mut it = Counter::new(0, 5).take_(10);
|
||||
let xs: ~[int] = iter::FromIter::from_iter::<int, ~[int]>(|f| it.advance(f));
|
||||
let xs: ~[int] = FromIterator::from_iterator(&mut it);
|
||||
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
||||
}
|
||||
|
||||
|
|
@ -983,6 +1148,19 @@ mod tests {
|
|||
assert_eq!(i, ys.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_flat_map() {
|
||||
let xs = [0u, 3, 6];
|
||||
let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
let mut it = xs.iter().flat_map_(|&x| Counter::new(x, 1).take_(3));
|
||||
let mut i = 0;
|
||||
for it.advance |x: uint| {
|
||||
assert_eq!(x, ys[i]);
|
||||
i += 1;
|
||||
}
|
||||
assert_eq!(i, ys.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unfoldr() {
|
||||
fn count(st: &mut uint) -> Option<uint> {
|
||||
|
|
@ -995,7 +1173,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
let mut it = UnfoldrIterator::new(count, 0);
|
||||
let mut it = UnfoldrIterator::new(0, count);
|
||||
let mut i = 0;
|
||||
for it.advance |counted| {
|
||||
assert_eq!(counted, i);
|
||||
|
|
@ -1020,11 +1198,11 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_count() {
|
||||
fn test_iterator_len() {
|
||||
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
assert_eq!(v.slice(0, 4).iter().count(), 4);
|
||||
assert_eq!(v.slice(0, 10).iter().count(), 10);
|
||||
assert_eq!(v.slice(0, 0).iter().count(), 0);
|
||||
assert_eq!(v.slice(0, 4).iter().len_(), 4);
|
||||
assert_eq!(v.slice(0, 10).iter().len_(), 10);
|
||||
assert_eq!(v.slice(0, 0).iter().len_(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1099,4 +1277,24 @@ mod tests {
|
|||
assert_eq!(v.iter().position_(|x| *x % 3 == 0).unwrap(), 1);
|
||||
assert!(v.iter().position_(|x| *x % 12 == 0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_count() {
|
||||
let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
|
||||
assert_eq!(xs.iter().count(|x| *x == 2), 3);
|
||||
assert_eq!(xs.iter().count(|x| *x == 5), 1);
|
||||
assert_eq!(xs.iter().count(|x| *x == 95), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_by() {
|
||||
let xs = [-3, 0, 1, 5, -10];
|
||||
assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min_by() {
|
||||
let xs = [-3, 0, 1, 5, -10];
|
||||
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
1229
src/libstd/libc.rs
1229
src/libstd/libc.rs
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,13 +16,12 @@ use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
|||
use option::{None, Option, Some};
|
||||
use char;
|
||||
use str;
|
||||
use str::{StrSlice};
|
||||
use str::StrSlice;
|
||||
use kinds::Copy;
|
||||
use vec;
|
||||
use vec::{CopyableVector, ImmutableVector};
|
||||
use vec::{CopyableVector, ImmutableVector, MutableVector};
|
||||
use vec::OwnedVector;
|
||||
use num::{NumCast, Zero, One, cast, pow_with_uint};
|
||||
use f64;
|
||||
use num::{NumCast, Zero, One, cast, pow_with_uint, Integer};
|
||||
use num::{Round, Float, FPNaN, FPInfinite};
|
||||
|
||||
pub enum ExponentFormat {
|
||||
ExpNone,
|
||||
|
|
@ -42,35 +41,6 @@ pub enum SignFormat {
|
|||
SignAll
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_NaN<T:Eq>(num: &T) -> bool {
|
||||
*num != *num
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_inf<T:Eq+NumStrConv>(num: &T) -> bool {
|
||||
match NumStrConv::inf() {
|
||||
None => false,
|
||||
Some(n) => *num == n
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool {
|
||||
match NumStrConv::neg_inf() {
|
||||
None => false,
|
||||
Some(n) => *num == n
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Div<T,T>>(num: &T) -> bool {
|
||||
let _0: T = Zero::zero();
|
||||
let _1: T = One::one();
|
||||
|
||||
*num == _0 && is_neg_inf(&(_1 / *num))
|
||||
}
|
||||
|
||||
pub trait NumStrConv {
|
||||
fn NaN() -> Option<Self>;
|
||||
fn inf() -> Option<Self>;
|
||||
|
|
@ -93,16 +63,9 @@ macro_rules! impl_NumStrConv_Floating (($t:ty) => (
|
|||
fn neg_zero() -> Option<$t> { Some(-0.0 ) }
|
||||
|
||||
#[inline]
|
||||
fn round_to_zero(&self) -> $t {
|
||||
( if *self < 0.0 { f64::ceil(*self as f64) }
|
||||
else { f64::floor(*self as f64) }
|
||||
) as $t
|
||||
}
|
||||
|
||||
fn round_to_zero(&self) -> $t { self.trunc() }
|
||||
#[inline]
|
||||
fn fractional_part(&self) -> $t {
|
||||
*self - self.round_to_zero()
|
||||
}
|
||||
fn fractional_part(&self) -> $t { self.fract() }
|
||||
}
|
||||
))
|
||||
|
||||
|
|
@ -145,6 +108,87 @@ static negative_inf_buf: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8,
|
|||
'f' as u8];
|
||||
static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
|
||||
|
||||
/**
|
||||
* Converts an integral number to its string representation as a byte vector.
|
||||
* This is meant to be a common base implementation for all integral string
|
||||
* conversion functions like `to_str()` or `to_str_radix()`.
|
||||
*
|
||||
* # Arguments
|
||||
* - `num` - The number to convert. Accepts any number that
|
||||
* implements the numeric traits.
|
||||
* - `radix` - Base to use. Accepts only the values 2-36.
|
||||
* - `sign` - How to emit the sign. Options are:
|
||||
* - `SignNone`: No sign at all. Basically emits `abs(num)`.
|
||||
* - `SignNeg`: Only `-` on negative values.
|
||||
* - `SignAll`: Both `+` on positive, and `-` on negative numbers.
|
||||
* - `f` - a callback which will be invoked for each ascii character
|
||||
* which composes the string representation of this integer
|
||||
*
|
||||
* # Return value
|
||||
* A tuple containing the byte vector, and a boolean flag indicating
|
||||
* whether it represents a special value like `inf`, `-inf`, `NaN` or not.
|
||||
* It returns a tuple because there can be ambiguity between a special value
|
||||
* and a number representation at higher bases.
|
||||
*
|
||||
* # Failure
|
||||
* - Fails if `radix` < 2 or `radix` > 36.
|
||||
*/
|
||||
pub fn int_to_str_bytes_common<T:NumCast+Zero+Eq+Ord+Integer+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
num: T, radix: uint, sign: SignFormat, f: &fn(u8)) {
|
||||
assert!(2 <= radix && radix <= 36);
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
|
||||
let neg = num < _0;
|
||||
let radix_gen: T = cast(radix);
|
||||
|
||||
let mut deccum = num;
|
||||
// This is just for integral types, the largest of which is a u64. The
|
||||
// smallest base that we can have is 2, so the most number of digits we're
|
||||
// ever going to have is 64
|
||||
let mut buf = [0u8, ..64];
|
||||
let mut cur = 0;
|
||||
|
||||
// Loop at least once to make sure at least a `0` gets emitted.
|
||||
loop {
|
||||
// Calculate the absolute value of each digit instead of only
|
||||
// doing it once for the whole number because a
|
||||
// representable negative number doesn't necessary have an
|
||||
// representable additive inverse of the same type
|
||||
// (See twos complement). But we assume that for the
|
||||
// numbers [-35 .. 0] we always have [0 .. 35].
|
||||
let current_digit_signed = deccum % radix_gen;
|
||||
let current_digit = if current_digit_signed < _0 {
|
||||
-current_digit_signed
|
||||
} else {
|
||||
current_digit_signed
|
||||
};
|
||||
buf[cur] = match current_digit.to_u8() {
|
||||
i @ 0..9 => '0' as u8 + i,
|
||||
i => 'a' as u8 + (i - 10),
|
||||
};
|
||||
cur += 1;
|
||||
|
||||
deccum = deccum / radix_gen;
|
||||
// No more digits to calculate for the non-fractional part -> break
|
||||
if deccum == _0 { break; }
|
||||
}
|
||||
|
||||
// Decide what sign to put in front
|
||||
match sign {
|
||||
SignNeg | SignAll if neg => { f('-' as u8); }
|
||||
SignAll => { f('+' as u8); }
|
||||
_ => ()
|
||||
}
|
||||
|
||||
// We built the number in reverse order, so un-reverse it here
|
||||
while cur > 0 {
|
||||
cur -= 1;
|
||||
f(buf[cur]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number to its string representation as a byte vector.
|
||||
* This is meant to be a common base implementation for all numeric string
|
||||
|
|
@ -176,44 +220,39 @@ static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
|
|||
* # Failure
|
||||
* - Fails if `radix` < 2 or `radix` > 36.
|
||||
*/
|
||||
pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
||||
pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
num: &T, radix: uint, negative_zero: bool,
|
||||
num: T, radix: uint, negative_zero: bool,
|
||||
sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
|
||||
if (radix as int) < 2 {
|
||||
fail!("to_str_bytes_common: radix %? to low, must lie in the range [2, 36]", radix);
|
||||
} else if radix as int > 36 {
|
||||
fail!("to_str_bytes_common: radix %? to high, must lie in the range [2, 36]", radix);
|
||||
}
|
||||
assert!(2 <= radix && radix <= 36);
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
let _1: T = One::one();
|
||||
|
||||
if is_NaN(num) {
|
||||
return ("NaN".as_bytes().to_owned(), true);
|
||||
}
|
||||
else if is_inf(num){
|
||||
return match sign {
|
||||
SignAll => ("+inf".as_bytes().to_owned(), true),
|
||||
_ => ("inf".as_bytes().to_owned(), true)
|
||||
match num.classify() {
|
||||
FPNaN => { return ("NaN".as_bytes().to_owned(), true); }
|
||||
FPInfinite if num > _0 => {
|
||||
return match sign {
|
||||
SignAll => ("+inf".as_bytes().to_owned(), true),
|
||||
_ => ("inf".as_bytes().to_owned(), true)
|
||||
};
|
||||
}
|
||||
}
|
||||
else if is_neg_inf(num) {
|
||||
return match sign {
|
||||
SignNone => ("inf".as_bytes().to_owned(), true),
|
||||
_ => ("-inf".as_bytes().to_owned(), true),
|
||||
FPInfinite if num < _0 => {
|
||||
return match sign {
|
||||
SignNone => ("inf".as_bytes().to_owned(), true),
|
||||
_ => ("-inf".as_bytes().to_owned(), true),
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let neg = *num < _0 || (negative_zero && is_neg_zero(num));
|
||||
let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
|
||||
let mut buf: ~[u8] = ~[];
|
||||
let radix_gen: T = cast(radix as int);
|
||||
|
||||
let mut deccum;
|
||||
|
||||
// First emit the non-fractional part, looping at least once to make
|
||||
// sure at least a `0` gets emitted.
|
||||
deccum = num.round_to_zero();
|
||||
let mut deccum = num.trunc();
|
||||
loop {
|
||||
// Calculate the absolute value of each digit instead of only
|
||||
// doing it once for the whole number because a
|
||||
|
|
@ -221,16 +260,11 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
|||
// representable additive inverse of the same type
|
||||
// (See twos complement). But we assume that for the
|
||||
// numbers [-35 .. 0] we always have [0 .. 35].
|
||||
let current_digit_signed = deccum % radix_gen;
|
||||
let current_digit = if current_digit_signed < _0 {
|
||||
-current_digit_signed
|
||||
} else {
|
||||
current_digit_signed
|
||||
};
|
||||
let current_digit = (deccum % radix_gen).abs();
|
||||
|
||||
// Decrease the deccumulator one digit at a time
|
||||
deccum = deccum / radix_gen;
|
||||
deccum = deccum.round_to_zero();
|
||||
deccum = deccum.trunc();
|
||||
|
||||
buf.push(char::from_digit(current_digit.to_int() as uint, radix)
|
||||
.unwrap() as u8);
|
||||
|
|
@ -257,7 +291,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
|||
_ => ()
|
||||
}
|
||||
|
||||
vec::reverse(buf);
|
||||
buf.reverse();
|
||||
|
||||
// Remember start of the fractional digits.
|
||||
// Points one beyond end of buf if none get generated,
|
||||
|
|
@ -265,7 +299,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
|||
let start_fractional_digits = buf.len();
|
||||
|
||||
// Now emit the fractional part, if any
|
||||
deccum = num.fractional_part();
|
||||
deccum = num.fract();
|
||||
if deccum != _0 || (limit_digits && exact && digit_count > 0) {
|
||||
buf.push('.' as u8);
|
||||
let mut dig = 0u;
|
||||
|
|
@ -286,18 +320,13 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
|||
|
||||
// Calculate the absolute value of each digit.
|
||||
// See note in first loop.
|
||||
let current_digit_signed = deccum.round_to_zero();
|
||||
let current_digit = if current_digit_signed < _0 {
|
||||
-current_digit_signed
|
||||
} else {
|
||||
current_digit_signed
|
||||
};
|
||||
let current_digit = deccum.trunc().abs();
|
||||
|
||||
buf.push(char::from_digit(
|
||||
current_digit.to_int() as uint, radix).unwrap() as u8);
|
||||
|
||||
// Decrease the deccumulator one fractional digit at a time
|
||||
deccum = deccum.fractional_part();
|
||||
deccum = deccum.fract();
|
||||
dig += 1u;
|
||||
}
|
||||
|
||||
|
|
@ -382,11 +411,11 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
|||
* `to_str_bytes_common()`, for details see there.
|
||||
*/
|
||||
#[inline]
|
||||
pub fn to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
num: &T, radix: uint, negative_zero: bool,
|
||||
pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+Round+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
num: T, radix: uint, negative_zero: bool,
|
||||
sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
|
||||
let (bytes, special) = to_str_bytes_common(num, radix,
|
||||
let (bytes, special) = float_to_str_bytes_common(num, radix,
|
||||
negative_zero, sign, digits);
|
||||
(str::from_bytes(bytes), special)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#[lang="drop"]
|
||||
pub trait Drop {
|
||||
fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton
|
||||
fn drop(&self);
|
||||
}
|
||||
|
||||
#[lang="add"]
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,11 @@ use cmp::Eq;
|
|||
use iterator::IteratorUtil;
|
||||
use libc;
|
||||
use option::{None, Option, Some};
|
||||
use str::{OwnedStr, Str, StrSlice, StrVector};
|
||||
use str;
|
||||
use str::{Str, StrSlice, StrVector};
|
||||
use to_str::ToStr;
|
||||
use ascii::{AsciiCast, AsciiStr};
|
||||
use old_iter::BaseIter;
|
||||
use vec::OwnedVector;
|
||||
use vec::{OwnedVector, ImmutableVector};
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use Path = self::WindowsPath;
|
||||
|
|
@ -128,7 +127,6 @@ pub trait GenericPath {
|
|||
#[cfg(target_os = "android")]
|
||||
mod stat {
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
pub mod arch {
|
||||
use libc;
|
||||
|
||||
|
|
@ -158,6 +156,35 @@ mod stat {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
pub mod arch {
|
||||
use libc;
|
||||
|
||||
pub fn default_stat() -> libc::stat {
|
||||
libc::stat {
|
||||
st_dev: 0,
|
||||
__pad0: [0, ..4],
|
||||
__st_ino: 0,
|
||||
st_mode: 0,
|
||||
st_nlink: 0,
|
||||
st_uid: 0,
|
||||
st_gid: 0,
|
||||
st_rdev: 0,
|
||||
__pad3: [0, ..4],
|
||||
st_size: 0,
|
||||
st_blksize: 0,
|
||||
st_blocks: 0,
|
||||
st_atime: 0,
|
||||
st_atime_nsec: 0,
|
||||
st_mtime: 0,
|
||||
st_mtime_nsec: 0,
|
||||
st_ctime: 0,
|
||||
st_ctime_nsec: 0,
|
||||
st_ino: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub mod arch {
|
||||
use libc;
|
||||
|
|
@ -308,8 +335,8 @@ mod stat {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl Path {
|
||||
#[cfg(target_os = "win32")]
|
||||
impl WindowsPath {
|
||||
pub fn stat(&self) -> Option<libc::stat> {
|
||||
unsafe {
|
||||
do str::as_c_str(self.to_str()) |buf| {
|
||||
|
|
@ -322,19 +349,6 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn lstat(&self) -> Option<libc::stat> {
|
||||
unsafe {
|
||||
do str::as_c_str(self.to_str()) |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match libc::lstat(buf, &mut st) {
|
||||
0 => Some(st),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
match self.stat() {
|
||||
None => false,
|
||||
|
|
@ -357,10 +371,55 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "win32"))]
|
||||
impl PosixPath {
|
||||
pub fn stat(&self) -> Option<libc::stat> {
|
||||
unsafe {
|
||||
do str::as_c_str(self.to_str()) |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match libc::stat(buf, &mut st) {
|
||||
0 => Some(st),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
match self.stat() {
|
||||
None => false,
|
||||
Some(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> Option<i64> {
|
||||
match self.stat() {
|
||||
None => None,
|
||||
Some(ref st) => Some(st.st_size as i64),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mode(&self) -> Option<uint> {
|
||||
match self.stat() {
|
||||
None => None,
|
||||
Some(ref st) => Some(st.st_mode as uint),
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute a function on p as well as all of its ancestors
|
||||
pub fn each_parent(&self, f: &fn(&Path)) {
|
||||
if !self.components.is_empty() {
|
||||
f(self);
|
||||
self.pop().each_parent(f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "macos")]
|
||||
impl Path {
|
||||
impl PosixPath {
|
||||
pub fn get_atime(&self) -> Option<(i64, int)> {
|
||||
match self.stat() {
|
||||
None => None,
|
||||
|
|
@ -392,9 +451,24 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl PosixPath {
|
||||
pub fn lstat(&self) -> Option<libc::stat> {
|
||||
unsafe {
|
||||
do str::as_c_str(self.to_str()) |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match libc::lstat(buf, &mut st) {
|
||||
0 => Some(st),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(target_os = "macos")]
|
||||
impl Path {
|
||||
impl PosixPath {
|
||||
pub fn get_birthtime(&self) -> Option<(i64, int)> {
|
||||
match self.stat() {
|
||||
None => None,
|
||||
|
|
@ -407,7 +481,7 @@ impl Path {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
impl Path {
|
||||
impl WindowsPath {
|
||||
pub fn get_atime(&self) -> Option<(i64, int)> {
|
||||
match self.stat() {
|
||||
None => None,
|
||||
|
|
@ -434,13 +508,21 @@ impl Path {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute a function on p as well as all of its ancestors
|
||||
pub fn each_parent(&self, f: &fn(&Path)) {
|
||||
if !self.components.is_empty() {
|
||||
f(self);
|
||||
self.pop().each_parent(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToStr for PosixPath {
|
||||
fn to_str(&self) -> ~str {
|
||||
let mut s = ~"";
|
||||
if self.is_absolute {
|
||||
s += "/";
|
||||
s.push_str("/");
|
||||
}
|
||||
s + self.components.connect("/")
|
||||
}
|
||||
|
|
@ -568,7 +650,7 @@ impl GenericPath for PosixPath {
|
|||
|
||||
fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
|
||||
let mut v = copy self.components;
|
||||
for cs.each |e| {
|
||||
for cs.iter().advance |e| {
|
||||
for e.as_slice().split_iter(windows::is_sep).advance |s| {
|
||||
if !s.is_empty() {
|
||||
v.push(s.to_owned())
|
||||
|
|
@ -619,15 +701,21 @@ impl ToStr for WindowsPath {
|
|||
fn to_str(&self) -> ~str {
|
||||
let mut s = ~"";
|
||||
match self.host {
|
||||
Some(ref h) => { s += "\\\\"; s += *h; }
|
||||
Some(ref h) => {
|
||||
s.push_str("\\\\");
|
||||
s.push_str(*h);
|
||||
}
|
||||
None => { }
|
||||
}
|
||||
match self.device {
|
||||
Some(ref d) => { s += *d; s += ":"; }
|
||||
Some(ref d) => {
|
||||
s.push_str(*d);
|
||||
s.push_str(":");
|
||||
}
|
||||
None => { }
|
||||
}
|
||||
if self.is_absolute {
|
||||
s += "\\";
|
||||
s.push_str("\\");
|
||||
}
|
||||
s + self.components.connect("\\")
|
||||
}
|
||||
|
|
@ -825,7 +913,7 @@ impl GenericPath for WindowsPath {
|
|||
|
||||
fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
|
||||
let mut v = copy self.components;
|
||||
for cs.each |e| {
|
||||
for cs.iter().advance |e| {
|
||||
for e.as_slice().split_iter(windows::is_sep).advance |s| {
|
||||
if !s.is_empty() {
|
||||
v.push(s.to_owned())
|
||||
|
|
@ -887,7 +975,7 @@ impl GenericPath for WindowsPath {
|
|||
|
||||
pub fn normalize(components: &[~str]) -> ~[~str] {
|
||||
let mut cs = ~[];
|
||||
for components.each |c| {
|
||||
for components.iter().advance |c| {
|
||||
if *c == ~"." && components.len() > 1 { loop; }
|
||||
if *c == ~"" { loop; }
|
||||
if *c == ~".." && cs.len() != 0 {
|
||||
|
|
|
|||
|
|
@ -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>]) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ More runtime type reflection
|
|||
use cast::transmute;
|
||||
use char;
|
||||
use container::Container;
|
||||
use intrinsic;
|
||||
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
|
||||
use intrinsic::Opaque;
|
||||
use io::{Writer, WriterUtil};
|
||||
use iterator::IteratorUtil;
|
||||
use libc::c_void;
|
||||
|
|
@ -34,6 +31,10 @@ use to_str::ToStr;
|
|||
use vec::raw::{VecRepr, SliceRepr};
|
||||
use vec;
|
||||
use vec::{OwnedVector, UnboxedVecRepr};
|
||||
#[cfg(stage0)]
|
||||
use intrinsic::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
|
||||
#[cfg(not(stage0))]
|
||||
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
|
||||
|
||||
#[cfg(test)] use io;
|
||||
|
||||
|
|
@ -56,9 +57,9 @@ impl EscapedCharWriter for @Writer {
|
|||
'"' => self.write_str("\\\""),
|
||||
'\x20'..'\x7e' => self.write_char(ch),
|
||||
_ => {
|
||||
// FIXME #4423: This is inefficient because it requires a
|
||||
// malloc.
|
||||
self.write_str(char::escape_unicode(ch))
|
||||
do char::escape_unicode(ch) |c| {
|
||||
self.write_char(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,65 +81,35 @@ impl Repr for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl Repr for int {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_int(*self); }
|
||||
}
|
||||
impl Repr for i8 {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
|
||||
}
|
||||
impl Repr for i16 {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
|
||||
}
|
||||
impl Repr for i32 {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
|
||||
}
|
||||
impl Repr for i64 {
|
||||
// FIXME #4424: This can lose precision.
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
|
||||
}
|
||||
|
||||
impl Repr for uint {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_uint(*self); }
|
||||
}
|
||||
impl Repr for u8 {
|
||||
macro_rules! int_repr(($ty:ident) => (impl Repr for $ty {
|
||||
fn write_repr(&self, writer: @Writer) {
|
||||
writer.write_uint(*self as uint);
|
||||
do ::$ty::to_str_bytes(*self, 10u) |bits| {
|
||||
writer.write(bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Repr for u16 {
|
||||
fn write_repr(&self, writer: @Writer) {
|
||||
writer.write_uint(*self as uint);
|
||||
}
|
||||
}
|
||||
impl Repr for u32 {
|
||||
fn write_repr(&self, writer: @Writer) {
|
||||
writer.write_uint(*self as uint);
|
||||
}
|
||||
}
|
||||
impl Repr for u64 {
|
||||
// FIXME #4424: This can lose precision.
|
||||
fn write_repr(&self, writer: @Writer) {
|
||||
writer.write_uint(*self as uint);
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
impl Repr for float {
|
||||
// FIXME #4423: This mallocs.
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
|
||||
}
|
||||
impl Repr for f32 {
|
||||
// FIXME #4423 This mallocs.
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
|
||||
}
|
||||
impl Repr for f64 {
|
||||
// FIXME #4423: This mallocs.
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
|
||||
}
|
||||
int_repr!(int)
|
||||
int_repr!(i8)
|
||||
int_repr!(i16)
|
||||
int_repr!(i32)
|
||||
int_repr!(i64)
|
||||
int_repr!(uint)
|
||||
int_repr!(u8)
|
||||
int_repr!(u16)
|
||||
int_repr!(u32)
|
||||
int_repr!(u64)
|
||||
|
||||
impl Repr for char {
|
||||
fn write_repr(&self, writer: @Writer) { writer.write_char(*self); }
|
||||
}
|
||||
macro_rules! num_repr(($ty:ident) => (impl Repr for $ty {
|
||||
fn write_repr(&self, writer: @Writer) {
|
||||
let s = self.to_str();
|
||||
writer.write(s.as_bytes());
|
||||
}
|
||||
}))
|
||||
|
||||
num_repr!(float)
|
||||
num_repr!(f32)
|
||||
num_repr!(f64)
|
||||
|
||||
// New implementation using reflect::MovePtr
|
||||
|
||||
|
|
@ -564,6 +535,7 @@ impl TyVisitor for ReprVisitor {
|
|||
fn visit_self(&self) -> bool { true }
|
||||
fn visit_type(&self) -> bool { true }
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_opaque_box(&self) -> bool {
|
||||
self.writer.write_char('@');
|
||||
do self.get::<&managed::raw::BoxRepr> |b| {
|
||||
|
|
@ -571,6 +543,16 @@ impl TyVisitor for ReprVisitor {
|
|||
self.visit_ptr_inner(p, b.header.type_desc);
|
||||
}
|
||||
}
|
||||
#[cfg(stage0)]
|
||||
fn visit_opaque_box(&self) -> bool {
|
||||
self.writer.write_char('@');
|
||||
do self.get::<&managed::raw::BoxRepr> |b| {
|
||||
let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
|
||||
unsafe {
|
||||
self.visit_ptr_inner(p, transmute(b.header.type_desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Type no longer exists, vestigial function.
|
||||
fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); }
|
||||
|
|
@ -581,7 +563,7 @@ impl TyVisitor for ReprVisitor {
|
|||
pub fn write_repr<T>(writer: @Writer, object: &T) {
|
||||
unsafe {
|
||||
let ptr = ptr::to_unsafe_ptr(object) as *c_void;
|
||||
let tydesc = intrinsic::get_tydesc::<T>();
|
||||
let tydesc = get_tydesc::<T>();
|
||||
let u = ReprVisitor(ptr, writer);
|
||||
let v = reflect::MovePtrAdaptor(u);
|
||||
visit_tydesc(tydesc, @v as @TyVisitor)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -8,104 +8,129 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use sys::{TypeDesc, size_of};
|
||||
use libc::{c_void, size_t, uintptr_t};
|
||||
use c_malloc = libc::malloc;
|
||||
use c_free = libc::free;
|
||||
use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
|
||||
use managed::raw::{BoxHeaderRepr, BoxRepr};
|
||||
use cast::transmute;
|
||||
use unstable::intrinsics::{atomic_xadd,atomic_xsub, atomic_load};
|
||||
use ptr::null;
|
||||
use intrinsic::TyDesc;
|
||||
use unstable::intrinsics::TyDesc;
|
||||
use sys::size_of;
|
||||
|
||||
pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
|
||||
assert!(td.is_not_null());
|
||||
|
||||
let total_size = get_box_size(size, (*td).align);
|
||||
let p = c_malloc(total_size as size_t);
|
||||
assert!(p.is_not_null());
|
||||
|
||||
// FIXME #3475: Converting between our two different tydesc types
|
||||
let td: *TyDesc = transmute(td);
|
||||
|
||||
let box: &mut BoxRepr = transmute(p);
|
||||
box.header.ref_count = -1; // Exchange values not ref counted
|
||||
box.header.type_desc = td;
|
||||
box.header.prev = null();
|
||||
box.header.next = null();
|
||||
|
||||
inc_count();
|
||||
|
||||
return transmute(box);
|
||||
}
|
||||
/**
|
||||
Thin wrapper around libc::malloc, none of the box header
|
||||
stuff in exchange_alloc::malloc
|
||||
*/
|
||||
pub unsafe fn malloc_raw(size: uint) -> *c_void {
|
||||
let p = c_malloc(size as size_t);
|
||||
if p.is_null() {
|
||||
fail!("Failure in malloc_raw: result ptr is null");
|
||||
}
|
||||
inc_count();
|
||||
p
|
||||
}
|
||||
|
||||
pub unsafe fn free(ptr: *c_void) {
|
||||
assert!(ptr.is_not_null());
|
||||
dec_count();
|
||||
c_free(ptr);
|
||||
}
|
||||
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
|
||||
pub unsafe fn free_raw(ptr: *c_void) {
|
||||
assert!(ptr.is_not_null());
|
||||
dec_count();
|
||||
c_free(ptr);
|
||||
}
|
||||
|
||||
fn inc_count() {
|
||||
unsafe {
|
||||
let exchange_count = &mut *exchange_count_ptr();
|
||||
atomic_xadd(exchange_count, 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn dec_count() {
|
||||
unsafe {
|
||||
let exchange_count = &mut *exchange_count_ptr();
|
||||
atomic_xsub(exchange_count, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cleanup() {
|
||||
unsafe {
|
||||
let count_ptr = exchange_count_ptr();
|
||||
let allocations = atomic_load(&*count_ptr);
|
||||
if allocations != 0 {
|
||||
rtabort!("exchange heap not empty on exit - %i dangling allocations", allocations);
|
||||
}
|
||||
}
|
||||
extern {
|
||||
#[rust_stack]
|
||||
fn abort();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_box_size(body_size: uint, body_align: uint) -> uint {
|
||||
let header_size = size_of::<BoxHeaderRepr>();
|
||||
// FIXME (#2699): This alignment calculation is suspicious. Is it right?
|
||||
let total_size = align_to(header_size, body_align) + body_size;
|
||||
return total_size;
|
||||
total_size
|
||||
}
|
||||
|
||||
// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
|
||||
// of two.
|
||||
#[inline]
|
||||
fn align_to(size: uint, align: uint) -> uint {
|
||||
assert!(align != 0);
|
||||
(size + align - 1) & !(align - 1)
|
||||
}
|
||||
|
||||
fn exchange_count_ptr() -> *mut int {
|
||||
// XXX: Need mutable globals
|
||||
unsafe { transmute(&rust_exchange_count) }
|
||||
/// A wrapper around libc::malloc, aborting on out-of-memory
|
||||
#[inline]
|
||||
pub unsafe fn malloc_raw(size: uint) -> *c_void {
|
||||
let p = malloc(size as size_t);
|
||||
if p.is_null() {
|
||||
// we need a non-allocating way to print an error here
|
||||
abort();
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
extern {
|
||||
static rust_exchange_count: uintptr_t;
|
||||
/// A wrapper around libc::realloc, aborting on out-of-memory
|
||||
#[inline]
|
||||
pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
|
||||
let p = realloc(ptr, size as size_t);
|
||||
if p.is_null() {
|
||||
// we need a non-allocating way to print an error here
|
||||
abort();
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
|
||||
#[cfg(stage0, not(test))]
|
||||
#[lang="exchange_malloc"]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
exchange_malloc(td, size)
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
let td = td as *TyDesc;
|
||||
let size = size as uint;
|
||||
|
||||
assert!(td.is_not_null());
|
||||
|
||||
let total_size = get_box_size(size, (*td).align);
|
||||
let p = malloc_raw(total_size as uint);
|
||||
|
||||
let box: *mut BoxRepr = p as *mut BoxRepr;
|
||||
(*box).header.ref_count = -1;
|
||||
(*box).header.type_desc = td;
|
||||
|
||||
box as *c_char
|
||||
}
|
||||
|
||||
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
|
||||
#[cfg(not(stage0), not(test))]
|
||||
#[lang="exchange_malloc"]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_malloc_(align: u32, size: uintptr_t) -> *c_char {
|
||||
exchange_malloc(align, size)
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char {
|
||||
let total_size = get_box_size(size as uint, align as uint);
|
||||
malloc_raw(total_size as uint) as *c_char
|
||||
}
|
||||
|
||||
// FIXME: #7496
|
||||
#[cfg(not(test))]
|
||||
#[lang="closure_exchange_malloc"]
|
||||
#[inline]
|
||||
pub unsafe fn closure_exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
closure_exchange_malloc(td, size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn closure_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
let td = td as *TyDesc;
|
||||
let size = size as uint;
|
||||
|
||||
assert!(td.is_not_null());
|
||||
|
||||
let total_size = get_box_size(size, (*td).align);
|
||||
let p = malloc_raw(total_size as uint);
|
||||
|
||||
let box: *mut BoxRepr = p as *mut BoxRepr;
|
||||
(*box).header.type_desc = td;
|
||||
|
||||
box as *c_char
|
||||
}
|
||||
|
||||
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
|
||||
// inside a landing pad may corrupt the state of the exception handler.
|
||||
#[cfg(not(test))]
|
||||
#[lang="exchange_free"]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_free_(ptr: *c_char) {
|
||||
exchange_free(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn exchange_free(ptr: *c_char) {
|
||||
free(ptr as *c_void);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(~[])
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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(||());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(~[])
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* Strings are a packed UTF-8 representation of text, stored as null
|
||||
* terminated buffers of u8 bytes. Strings should be indexed in bytes,
|
||||
* for efficiency, but UTF-8 unsafe operations should be avoided. For
|
||||
* some heavy-duty uses, try std::rope.
|
||||
* some heavy-duty uses, try extra::rope.
|
||||
*/
|
||||
|
||||
use at_vec;
|
||||
|
|
@ -29,7 +29,6 @@ use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator, MapIter
|
|||
use libc;
|
||||
use num::Zero;
|
||||
use option::{None, Option, Some};
|
||||
use old_iter::{BaseIter, EqIter};
|
||||
use ptr;
|
||||
use ptr::RawPtr;
|
||||
use to_str::ToStr;
|
||||
|
|
@ -55,12 +54,11 @@ Section: Creating a string
|
|||
*
|
||||
* Raises the `not_utf8` condition if invalid UTF-8
|
||||
*/
|
||||
|
||||
pub fn from_bytes(vv: &[u8]) -> ~str {
|
||||
use str::not_utf8::cond;
|
||||
|
||||
if !is_utf8(vv) {
|
||||
let first_bad_byte = vec::find(vv, |b| !is_utf8([*b])).get();
|
||||
let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).get();
|
||||
cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
|
||||
first_bad_byte as uint))
|
||||
}
|
||||
|
|
@ -69,6 +67,25 @@ pub fn from_bytes(vv: &[u8]) -> ~str {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes a vector of bytes to create a new utf-8 string
|
||||
*
|
||||
* # Failure
|
||||
*
|
||||
* Raises the `not_utf8` condition if invalid UTF-8
|
||||
*/
|
||||
pub fn from_bytes_owned(vv: ~[u8]) -> ~str {
|
||||
use str::not_utf8::cond;
|
||||
|
||||
if !is_utf8(vv) {
|
||||
let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).get();
|
||||
cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
|
||||
first_bad_byte as uint))
|
||||
} else {
|
||||
return unsafe { raw::from_bytes_owned(vv) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a vector of bytes to a UTF-8 string.
|
||||
* The vector needs to be one byte longer than the string, and end with a 0 byte.
|
||||
|
|
@ -147,7 +164,7 @@ pub fn from_char(ch: char) -> ~str {
|
|||
pub fn from_chars(chs: &[char]) -> ~str {
|
||||
let mut buf = ~"";
|
||||
buf.reserve(chs.len());
|
||||
for chs.each |ch| {
|
||||
for chs.iter().advance |ch| {
|
||||
buf.push_char(*ch)
|
||||
}
|
||||
buf
|
||||
|
|
@ -358,7 +375,8 @@ impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> {
|
|||
fn next(&mut self) -> Option<(uint, uint)> {
|
||||
// See Issue #1932 for why this is a naive search
|
||||
let (h_len, n_len) = (self.haystack.len(), self.needle.len());
|
||||
let mut (match_start, match_i) = (0, 0);
|
||||
let mut match_start = 0;
|
||||
let mut match_i = 0;
|
||||
|
||||
while self.position < h_len {
|
||||
if self.haystack[self.position] == self.needle[match_i] {
|
||||
|
|
@ -434,10 +452,17 @@ pub fn each_split_within<'a>(ss: &'a str,
|
|||
let mut last_start = 0;
|
||||
let mut last_end = 0;
|
||||
let mut state = A;
|
||||
let mut fake_i = ss.len();
|
||||
let mut lim = lim;
|
||||
|
||||
let mut cont = true;
|
||||
let slice: &fn() = || { cont = it(ss.slice(slice_start, last_end)) };
|
||||
|
||||
// if the limit is larger than the string, lower it to save cycles
|
||||
if (lim >= fake_i) {
|
||||
lim = fake_i;
|
||||
}
|
||||
|
||||
let machine: &fn((uint, char)) -> bool = |(i, c)| {
|
||||
let whitespace = if char::is_whitespace(c) { Ws } else { Cr };
|
||||
let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim };
|
||||
|
|
@ -463,10 +488,9 @@ pub fn each_split_within<'a>(ss: &'a str,
|
|||
cont
|
||||
};
|
||||
|
||||
ss.iter().enumerate().advance(machine);
|
||||
ss.iter().enumerate().advance(|x| machine(x));
|
||||
|
||||
// Let the automaton 'run out' by supplying trailing whitespace
|
||||
let mut fake_i = ss.len();
|
||||
while cont && match state { B | C => true, A => false } {
|
||||
machine((fake_i, ' '));
|
||||
fake_i += 1;
|
||||
|
|
@ -474,6 +498,31 @@ pub fn each_split_within<'a>(ss: &'a str,
|
|||
return cont;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all occurrences of one string with another
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * s - The string containing substrings to replace
|
||||
* * from - The string to replace
|
||||
* * to - The replacement string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The original string with all occurances of `from` replaced with `to`
|
||||
*/
|
||||
pub fn replace(s: &str, from: &str, to: &str) -> ~str {
|
||||
let mut result = ~"";
|
||||
let mut last_end = 0;
|
||||
for s.matches_index_iter(from).advance |(start, end)| {
|
||||
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
|
||||
result.push_str(to);
|
||||
last_end = end;
|
||||
}
|
||||
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
|
||||
result
|
||||
}
|
||||
|
||||
/*
|
||||
Section: Comparing strings
|
||||
*/
|
||||
|
|
@ -544,7 +593,7 @@ Section: Misc
|
|||
*/
|
||||
|
||||
/// Determines if a vector of bytes contains valid UTF-8
|
||||
pub fn is_utf8(v: &const [u8]) -> bool {
|
||||
pub fn is_utf8(v: &[u8]) -> bool {
|
||||
let mut i = 0u;
|
||||
let total = v.len();
|
||||
while i < total {
|
||||
|
|
@ -632,6 +681,48 @@ pub fn with_capacity(capacity: uint) -> ~str {
|
|||
buf
|
||||
}
|
||||
|
||||
/**
|
||||
* As char_len but for a slice of a string
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * s - A valid string
|
||||
* * start - The position inside `s` where to start counting in bytes
|
||||
* * end - The position where to stop counting
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The number of Unicode characters in `s` between the given indices.
|
||||
*/
|
||||
pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
|
||||
assert!(s.is_char_boundary(start));
|
||||
assert!(s.is_char_boundary(end));
|
||||
let mut i = start;
|
||||
let mut len = 0u;
|
||||
while i < end {
|
||||
let next = s.char_range_at(i).next;
|
||||
len += 1u;
|
||||
i = next;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/// Counts the number of bytes taken by the first `n` chars in `s`
|
||||
/// starting from `start`.
|
||||
pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
|
||||
assert!(s.is_char_boundary(start));
|
||||
let mut end = start;
|
||||
let mut cnt = n;
|
||||
let l = s.len();
|
||||
while cnt > 0u {
|
||||
assert!(end < l);
|
||||
let next = s.char_range_at(end).next;
|
||||
cnt -= 1u;
|
||||
end = next;
|
||||
}
|
||||
end - start
|
||||
}
|
||||
|
||||
/// Given a first byte, determine how many bytes are in this UTF-8 character
|
||||
pub fn utf8_char_width(b: u8) -> uint {
|
||||
let byte: uint = b as uint;
|
||||
|
|
@ -694,7 +785,7 @@ impl<'self> StrUtil for &'self str {
|
|||
// NB: len includes the trailing null.
|
||||
assert!(len > 0);
|
||||
if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
|
||||
to_owned(self).as_c_str(f)
|
||||
to_owned(self).as_c_str(|s| f(s))
|
||||
} else {
|
||||
f(buf as *libc::c_char)
|
||||
}
|
||||
|
|
@ -738,7 +829,8 @@ pub mod raw {
|
|||
|
||||
/// Create a Rust string from a null-terminated *u8 buffer
|
||||
pub unsafe fn from_buf(buf: *u8) -> ~str {
|
||||
let mut (curr, i) = (buf, 0u);
|
||||
let mut curr = buf;
|
||||
let mut i = 0u;
|
||||
while *curr != 0u8 {
|
||||
i += 1u;
|
||||
curr = ptr::offset(buf, i);
|
||||
|
|
@ -747,7 +839,7 @@ pub mod raw {
|
|||
}
|
||||
|
||||
/// Create a Rust string from a *u8 buffer of the given length
|
||||
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> ~str {
|
||||
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
|
||||
let mut v: ~[u8] = vec::with_capacity(len + 1);
|
||||
vec::as_mut_buf(v, |vbuf, _len| {
|
||||
ptr::copy_memory(vbuf, buf as *u8, len)
|
||||
|
|
@ -770,12 +862,19 @@ pub mod raw {
|
|||
}
|
||||
|
||||
/// Converts a vector of bytes to a new owned string.
|
||||
pub unsafe fn from_bytes(v: &const [u8]) -> ~str {
|
||||
do vec::as_const_buf(v) |buf, len| {
|
||||
pub unsafe fn from_bytes(v: &[u8]) -> ~str {
|
||||
do vec::as_imm_buf(v) |buf, len| {
|
||||
from_buf_len(buf, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an owned vector of bytes to a new owned string. This assumes
|
||||
/// that the utf-8-ness of the vector has already been validated
|
||||
pub unsafe fn from_bytes_owned(mut v: ~[u8]) -> ~str {
|
||||
v.push(0u8);
|
||||
cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Converts a vector of bytes to a string.
|
||||
/// The byte slice needs to contain valid utf8 and needs to be one byte longer than
|
||||
/// the string, if possible ending in a 0 byte.
|
||||
|
|
@ -791,7 +890,8 @@ pub mod raw {
|
|||
/// invalidated later.
|
||||
pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
|
||||
let s = s as *u8;
|
||||
let mut (curr, len) = (s, 0u);
|
||||
let mut curr = s;
|
||||
let mut len = 0u;
|
||||
while *curr != 0u8 {
|
||||
len += 1u;
|
||||
curr = ptr::offset(s, len);
|
||||
|
|
@ -864,7 +964,7 @@ pub mod raw {
|
|||
unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
|
||||
let new_len = s.len() + bytes.len();
|
||||
s.reserve_at_least(new_len);
|
||||
for bytes.each |byte| { push_byte(&mut *s, *byte); }
|
||||
for bytes.iter().advance |byte| { push_byte(&mut *s, *byte); }
|
||||
}
|
||||
|
||||
/// Removes the last byte from a string and returns it. (Not UTF-8 safe).
|
||||
|
|
@ -1071,6 +1171,17 @@ impl<'self> Str for @str {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'self> Container for &'self str {
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
do as_buf(*self) |_p, n| { n - 1u }
|
||||
}
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_doc)]
|
||||
pub trait StrSlice<'self> {
|
||||
fn contains<'a>(&self, needle: &'a str) -> bool;
|
||||
|
|
@ -1089,10 +1200,8 @@ pub trait StrSlice<'self> {
|
|||
fn any_line_iter(&self) -> AnyLineIterator<'self>;
|
||||
fn word_iter(&self) -> WordIterator<'self>;
|
||||
fn ends_with(&self, needle: &str) -> bool;
|
||||
fn is_empty(&self) -> bool;
|
||||
fn is_whitespace(&self) -> bool;
|
||||
fn is_alphanumeric(&self) -> bool;
|
||||
fn len(&self) -> uint;
|
||||
fn char_len(&self) -> uint;
|
||||
|
||||
fn slice(&self, begin: uint, end: uint) -> &'self str;
|
||||
|
|
@ -1293,9 +1402,6 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
self.split_iter(char::is_whitespace).filter(|s| !s.is_empty())
|
||||
}
|
||||
|
||||
/// Returns true if the string has length 0
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool { self.len() == 0 }
|
||||
/**
|
||||
* Returns true if the string contains only whitespace
|
||||
*
|
||||
|
|
@ -1310,14 +1416,9 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
*/
|
||||
#[inline]
|
||||
fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) }
|
||||
/// Returns the size in bytes not counting the null terminator
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
do as_buf(*self) |_p, n| { n - 1u }
|
||||
}
|
||||
/// Returns the number of characters that a string holds
|
||||
#[inline]
|
||||
fn char_len(&self) -> uint { self.iter().count() }
|
||||
fn char_len(&self) -> uint { self.iter().len_() }
|
||||
|
||||
/**
|
||||
* Returns a slice of the given string from the byte range
|
||||
|
|
@ -1358,7 +1459,8 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
fn slice_chars(&self, begin: uint, end: uint) -> &'self str {
|
||||
assert!(begin <= end);
|
||||
// not sure how to use the iterators for this nicely.
|
||||
let mut (position, count) = (0, 0);
|
||||
let mut position = 0;
|
||||
let mut count = 0;
|
||||
let l = self.len();
|
||||
while count < begin && position < l {
|
||||
position = self.char_range_at(position).next;
|
||||
|
|
@ -1395,7 +1497,9 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
let mut out: ~str = ~"";
|
||||
out.reserve_at_least(self.len());
|
||||
for self.iter().advance |c| {
|
||||
out.push_str(char::escape_default(c));
|
||||
do c.escape_default |c| {
|
||||
out.push_char(c);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
|
@ -1405,7 +1509,9 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
let mut out: ~str = ~"";
|
||||
out.reserve_at_least(self.len());
|
||||
for self.iter().advance |c| {
|
||||
out.push_str(char::escape_unicode(c));
|
||||
do c.escape_unicode |c| {
|
||||
out.push_char(c);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
|
@ -1506,7 +1612,8 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||
* The original string with all occurances of `from` replaced with `to`
|
||||
*/
|
||||
pub fn replace(&self, from: &str, to: &str) -> ~str {
|
||||
let mut (result, last_end) = (~"", 0);
|
||||
let mut result = ~"";
|
||||
let mut last_end = 0;
|
||||
for self.matches_index_iter(from).advance |(start, end)| {
|
||||
result.push_str(unsafe{raw::slice_bytes(*self, last_end, start)});
|
||||
result.push_str(to);
|
||||
|
|
@ -2082,7 +2189,7 @@ impl OwnedStr for ~str {
|
|||
pub fn reserve(&mut self, n: uint) {
|
||||
unsafe {
|
||||
let v: *mut ~[u8] = cast::transmute(self);
|
||||
vec::reserve(&mut *v, n + 1);
|
||||
(*v).reserve(n + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2116,8 +2223,8 @@ impl OwnedStr for ~str {
|
|||
* reallocating
|
||||
*/
|
||||
fn capacity(&self) -> uint {
|
||||
let buf: &const ~[u8] = unsafe { cast::transmute(self) };
|
||||
let vcap = vec::capacity(buf);
|
||||
let buf: &~[u8] = unsafe { cast::transmute(self) };
|
||||
let vcap = buf.capacity();
|
||||
assert!(vcap > 0u);
|
||||
vcap - 1u
|
||||
}
|
||||
|
|
@ -2225,9 +2332,9 @@ mod tests {
|
|||
use option::Some;
|
||||
use libc::c_char;
|
||||
use libc;
|
||||
use old_iter::BaseIter;
|
||||
use ptr;
|
||||
use str::*;
|
||||
use uint;
|
||||
use vec;
|
||||
use vec::{ImmutableVector, CopyableVector};
|
||||
use cmp::{TotalOrd, Less, Equal, Greater};
|
||||
|
|
@ -2251,7 +2358,7 @@ mod tests {
|
|||
assert!("" <= "");
|
||||
assert!("" <= "foo");
|
||||
assert!("foo" <= "foo");
|
||||
assert!("foo" != ~"bar");
|
||||
assert!("foo" != "bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2373,6 +2480,8 @@ mod tests {
|
|||
t("hello", 15, [~"hello"]);
|
||||
t("\nMary had a little lamb\nLittle lamb\n", 15,
|
||||
[~"Mary had a", ~"little lamb", ~"Little lamb"]);
|
||||
t("\nMary had a little lamb\nLittle lamb\n", uint::max_value,
|
||||
[~"Mary had a little lamb\nLittle lamb"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -3080,7 +3189,7 @@ mod tests {
|
|||
0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
|
||||
0x000a_u16 ]) ];
|
||||
|
||||
for pairs.each |p| {
|
||||
for pairs.iter().advance |p| {
|
||||
let (s, u) = copy *p;
|
||||
assert!(s.to_utf16() == u);
|
||||
assert!(from_utf16(u) == s);
|
||||
|
|
@ -3094,7 +3203,7 @@ mod tests {
|
|||
let s = ~"ศไทย中华Việt Nam";
|
||||
let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
|
||||
let mut pos = 0;
|
||||
for v.each |ch| {
|
||||
for v.iter().advance |ch| {
|
||||
assert!(s.char_at(pos) == *ch);
|
||||
pos += from_char(*ch).len();
|
||||
}
|
||||
|
|
@ -3158,6 +3267,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
#[allow(unnecessary_allocation)];
|
||||
macro_rules! t (
|
||||
($s1:expr, $s2:expr, $e:expr) => {
|
||||
assert_eq!($s1 + $s2, $e);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct Finallyalizer<'self> {
|
|||
|
||||
#[unsafe_destructor]
|
||||
impl<'self> Drop for Finallyalizer<'self> {
|
||||
fn finalize(&self) {
|
||||
fn drop(&self) {
|
||||
(self.dtor)();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2426
src/libstd/vec.rs
2426
src/libstd/vec.rs
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue