]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/ptr.rs
use TotalEq for HashMap
[rust.git] / src / libstd / ptr.rs
index 9cf36adc36f23da64f00103d7be5af44c85f64e1..504c613bf4c1763e4e7f15eb53895b37df395c67 100644 (file)
 #[cfg(not(test))]
 use cmp::Equiv;
 use iter::{range, Iterator};
+use mem;
 use option::{Option, Some, None};
-use unstable::intrinsics;
-use util::swap;
+use intrinsics;
 
-#[cfg(not(test))] use cmp::{Eq, Ord};
-
-/// Calculate the offset from a pointer.
-/// The `count` argument is in units of T; e.g. a `count` of 3
-/// represents a pointer offset of `3 * sizeof::<T>()` bytes.
-#[inline]
-pub unsafe fn offset<T>(ptr: *T, count: int) -> *T {
-    intrinsics::offset(ptr, count)
-}
-
-/// Calculate the offset from a mut pointer. The count *must* be in bounds or
-/// otherwise the loads of this address are undefined.
-/// The `count` argument is in units of T; e.g. a `count` of 3
-/// represents a pointer offset of `3 * sizeof::<T>()` bytes.
-#[inline]
-pub unsafe fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
-    intrinsics::offset(ptr as *T, count) as *mut T
-}
+#[cfg(not(test))] use cmp::{Eq, TotalEq, Ord};
 
 /// Return the offset of the first null pointer in `buf`.
 #[inline]
@@ -63,7 +46,7 @@ fn clone(&self) -> *mut T {
 pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
     let mut i = 0;
     loop {
-        if f(&(*offset(buf, i as int))) { return i; }
+        if f(&(*buf.offset(i as int))) { return i; }
         else { i += 1; }
     }
 }
@@ -76,14 +59,6 @@ pub fn null<T>() -> *T { 0 as *T }
 #[inline]
 pub fn mut_null<T>() -> *mut T { 0 as *mut T }
 
-/// Returns true if the pointer is equal to the null pointer.
-#[inline]
-pub fn is_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_null() }
-
-/// Returns true if the pointer is not equal to the null pointer.
-#[inline]
-pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
-
 /**
  * Copies data from one location to another.
  *
@@ -91,8 +66,8 @@ pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
  * and destination may overlap.
  */
 #[inline]
-pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
-    intrinsics::copy_memory(dst, cast::transmute_immut_unsafe(src), count)
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *T, count: uint) {
+    intrinsics::copy_memory(dst, src, count)
 }
 
 /**
@@ -102,10 +77,10 @@ pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
  * and destination may *not* overlap.
  */
 #[inline]
-pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
-                                                        src: P,
-                                                        count: uint) {
-    intrinsics::copy_nonoverlapping_memory(dst, cast::transmute_immut_unsafe(src), count)
+pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T,
+                                            src: *T,
+                                            count: uint) {
+    intrinsics::copy_nonoverlapping_memory(dst, src, count)
 }
 
 /**
@@ -127,18 +102,18 @@ pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
 
 /**
  * Swap the values at two mutable locations of the same type, without
- * deinitialising or copying either one.
+ * deinitialising either. They may overlap.
  */
 #[inline]
-pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
+pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // Give ourselves some scratch space to work with
-    let mut tmp: T = intrinsics::uninit();
+    let mut tmp: T = mem::uninit();
     let t: *mut T = &mut tmp;
 
     // Perform the swap
-    copy_nonoverlapping_memory(t, x, 1);
-    copy_memory(x, y, 1); // `x` and `y` may overlap
-    copy_nonoverlapping_memory(y, t, 1);
+    copy_nonoverlapping_memory(t, &*x, 1);
+    copy_memory(x, &*y, 1); // `x` and `y` may overlap
+    copy_nonoverlapping_memory(y, &*t, 1);
 
     // y and t now point to the same thing, but we need to completely forget `tmp`
     // because it's no longer relevant.
@@ -147,20 +122,20 @@ pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
 
 /**
  * Replace the value at a mutable location with a new one, returning the old
- * value, without deinitialising or copying either one.
+ * value, without deinitialising either.
  */
 #[inline]
-pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
-    swap(cast::transmute(dest), &mut src); // cannot overlap
+pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
+    mem::swap(cast::transmute(dest), &mut src); // cannot overlap
     src
 }
 
 /**
- * Reads the value from `*src` and returns it. Does not copy `*src`.
+ * Reads the value from `*src` and returns it.
  */
 #[inline(always)]
-pub unsafe fn read_ptr<T>(src: *T) -> T {
-    let mut tmp: T = intrinsics::uninit();
+pub unsafe fn read<T>(src: *T) -> T {
+    let mut tmp: T = mem::uninit();
     copy_nonoverlapping_memory(&mut tmp, src, 1);
     tmp
 }
@@ -170,9 +145,9 @@ pub unsafe fn read_ptr<T>(src: *T) -> T {
  * This currently prevents destructors from executing.
  */
 #[inline(always)]
-pub unsafe fn read_and_zero_ptr<T>(dest: *mut T) -> T {
+pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     // Copy the data out from `dest`:
-    let tmp = read_ptr(&*dest);
+    let tmp = read(&*dest);
 
     // Now zero out `dest`:
     zero_memory(dest, 1);
@@ -180,18 +155,6 @@ pub unsafe fn read_and_zero_ptr<T>(dest: *mut T) -> T {
     tmp
 }
 
-/// Transform a region pointer - &T - to an unsafe pointer - *T.
-#[inline]
-pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
-    thing as *T
-}
-
-/// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T.
-#[inline]
-pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
-    thing as *mut T
-}
-
 /**
   Given a **T (pointer to an array of pointers),
   iterate through each *T, up to the provided `len`,
@@ -200,16 +163,14 @@ pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
   SAFETY NOTE: Pointer-arithmetic. Dragons be here.
 */
 pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
-    debug!("array_each_with_len: before iterate");
-    if (arr as uint == 0) {
+    if arr.is_null() {
         fail!("ptr::array_each_with_len failure: arr input is null pointer");
     }
     //let start_ptr = *arr;
     for e in range(0, len) {
-        let n = offset(arr, e as int);
+        let n = arr.offset(e as int);
         cb(*n);
     }
-    debug!("array_each_with_len: after iterate");
 }
 
 /**
@@ -222,108 +183,82 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
   Dragons be here.
 */
 pub unsafe fn array_each<T>(arr: **T, cb: |*T|) {
-    if (arr as uint == 0) {
+    if arr.is_null()  {
         fail!("ptr::array_each_with_len failure: arr input is null pointer");
     }
     let len = buf_len(arr);
-    debug!("array_each inferred len: {}", len);
     array_each_with_len(arr, len, cb);
 }
 
-#[allow(missing_doc)]
+/// Extension methods for raw pointers.
 pub trait RawPtr<T> {
+    /// Returns the null pointer.
     fn null() -> Self;
+    /// Returns true if the pointer is equal to the null pointer.
     fn is_null(&self) -> bool;
-    fn is_not_null(&self) -> bool;
+    /// Returns true if the pointer is not equal to the null pointer.
+    fn is_not_null(&self) -> bool { !self.is_null() }
+    /// Returns the value of this pointer (ie, the address it points to)
     fn to_uint(&self) -> uint;
+    /// Returns `None` if the pointer is null, or else returns the value wrapped
+    /// in `Some`.
+    ///
+    /// # Safety Notes
+    ///
+    /// While this method is useful for null-safety, it is important to note
+    /// that this is still an unsafe operation because the returned value could
+    /// be pointing to invalid memory.
     unsafe fn to_option(&self) -> Option<&T>;
+    /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+    /// the object, or one-byte-past-the-end.  `count` is in units of T; e.g. a
+    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
     unsafe fn offset(self, count: int) -> Self;
 }
 
-/// Extension methods for immutable pointers
 impl<T> RawPtr<T> for *T {
-    /// Returns the null pointer.
     #[inline]
     fn null() -> *T { null() }
 
-    /// Returns true if the pointer is equal to the null pointer.
     #[inline]
     fn is_null(&self) -> bool { *self == RawPtr::null() }
 
-    /// Returns true if the pointer is not equal to the null pointer.
     #[inline]
-    fn is_not_null(&self) -> bool { *self != RawPtr::null() }
+    fn to_uint(&self) -> uint { *self as uint }
 
-    /// Returns the address of this pointer.
     #[inline]
-    fn to_uint(&self) -> uint { *self as uint }
+    unsafe fn offset(self, count: int) -> *T { intrinsics::offset(self, count) }
 
-    ///
-    /// Returns `None` if the pointer is null, or else returns the value wrapped
-    /// in `Some`.
-    ///
-    /// # Safety Notes
-    ///
-    /// While this method is useful for null-safety, it is important to note
-    /// that this is still an unsafe operation because the returned value could
-    /// be pointing to invalid memory.
-    ///
     #[inline]
     unsafe fn to_option(&self) -> Option<&T> {
-        if self.is_null() { None } else {
+        if self.is_null() {
+            None
+        } else {
             Some(cast::transmute(*self))
         }
     }
-
-    /// Calculates the offset from a pointer. The offset *must* be in-bounds of
-    /// the object, or one-byte-past-the-end.
-    #[inline]
-    unsafe fn offset(self, count: int) -> *T { offset(self, count) }
 }
 
-/// Extension methods for mutable pointers
 impl<T> RawPtr<T> for *mut T {
-    /// Returns the null pointer.
     #[inline]
     fn null() -> *mut T { mut_null() }
 
-    /// Returns true if the pointer is equal to the null pointer.
     #[inline]
     fn is_null(&self) -> bool { *self == RawPtr::null() }
 
-    /// Returns true if the pointer is not equal to the null pointer.
     #[inline]
-    fn is_not_null(&self) -> bool { *self != RawPtr::null() }
+    fn to_uint(&self) -> uint { *self as uint }
 
-    /// Returns the address of this pointer.
     #[inline]
-    fn to_uint(&self) -> uint { *self as uint }
+    unsafe fn offset(self, count: int) -> *mut T { intrinsics::offset(self as *T, count) as *mut T }
 
-    ///
-    /// Returns `None` if the pointer is null, or else returns the value wrapped
-    /// in `Some`.
-    ///
-    /// # Safety Notes
-    ///
-    /// While this method is useful for null-safety, it is important to note
-    /// that this is still an unsafe operation because the returned value could
-    /// be pointing to invalid memory.
-    ///
     #[inline]
     unsafe fn to_option(&self) -> Option<&T> {
-        if self.is_null() { None } else {
+        if self.is_null() {
+            None
+        } else {
             Some(cast::transmute(*self))
         }
     }
-
-    /// Calculates the offset from a pointer. The offset *must* be in-bounds of
-    /// the object, or one-byte-past-the-end. An arithmetic overflow is also
-    /// undefined behaviour.
-    ///
-    /// This method should be preferred over `offset` when the guarantee can be
-    /// satisfied, to enable better optimization.
-    #[inline]
-    unsafe fn offset(self, count: int) -> *mut T { mut_offset(self, count) }
 }
 
 // Equality for pointers
@@ -337,6 +272,9 @@ fn eq(&self, other: &*T) -> bool {
     fn ne(&self, other: &*T) -> bool { !self.eq(other) }
 }
 
+#[cfg(not(test))]
+impl<T> TotalEq for *T {}
+
 #[cfg(not(test))]
 impl<T> Eq for *mut T {
     #[inline]
@@ -347,6 +285,9 @@ fn eq(&self, other: &*mut T) -> bool {
     fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
 }
 
+#[cfg(not(test))]
+impl<T> TotalEq for *mut T {}
+
 // Equivalence for pointers
 #[cfg(not(test))]
 impl<T> Equiv<*mut T> for *T {
@@ -453,7 +394,7 @@ pub mod ptr_tests {
     use cast;
     use libc;
     use str;
-    use vec::{ImmutableVector, MutableVector};
+    use slice::{ImmutableVector, MutableVector};
 
     #[test]
     fn test() {
@@ -478,14 +419,14 @@ struct Pair {
             let v0 = ~[32000u16, 32001u16, 32002u16];
             let mut v1 = ~[0u16, 0u16, 0u16];
 
-            copy_memory(mut_offset(v1.as_mut_ptr(), 1),
-                        offset(v0.as_ptr(), 1), 1);
+            copy_memory(v1.as_mut_ptr().offset(1),
+                        v0.as_ptr().offset(1), 1);
             assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
             copy_memory(v1.as_mut_ptr(),
-                        offset(v0.as_ptr(), 2), 1);
+                        v0.as_ptr().offset(2), 1);
             assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
                      v1[2] == 0u16));
-            copy_memory(mut_offset(v1.as_mut_ptr(), 2),
+            copy_memory(v1.as_mut_ptr().offset(2),
                         v0.as_ptr(), 1u);
             assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
                      v1[2] == 32000u16));
@@ -525,7 +466,7 @@ fn test_is_null() {
         assert!(p.is_null());
         assert!(!p.is_not_null());
 
-        let q = unsafe { offset(p, 1) };
+        let q = unsafe { p.offset(1) };
         assert!(!q.is_null());
         assert!(q.is_not_null());
 
@@ -698,6 +639,6 @@ fn test_set_memory() {
         let mut xs = [0u8, ..20];
         let ptr = xs.as_mut_ptr();
         unsafe { set_memory(ptr, 5u8, xs.len()); }
-        assert_eq!(xs, [5u8, ..20]);
+        assert!(xs == [5u8, ..20]);
     }
 }