]> git.lizzy.rs Git - rust.git/blob - src/libstd/ptr.rs
auto merge of #10977 : brson/rust/androidtest, r=brson
[rust.git] / src / libstd / ptr.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Unsafe pointer utility functions
12
13 use cast;
14 use clone::Clone;
15 #[cfg(not(test))]
16 use cmp::Equiv;
17 use iter::{range, Iterator};
18 use option::{Option, Some, None};
19 use unstable::intrinsics;
20 use util::swap;
21
22 #[cfg(not(test))] use cmp::{Eq, Ord};
23
24 /// Calculate the offset from a pointer.
25 /// The `count` argument is in units of T; e.g. a `count` of 3
26 /// represents a pointer offset of `3 * sizeof::<T>()` bytes.
27 #[inline]
28 pub unsafe fn offset<T>(ptr: *T, count: int) -> *T {
29     intrinsics::offset(ptr, count)
30 }
31
32 /// Calculate the offset from a mut pointer. The count *must* be in bounds or
33 /// otherwise the loads of this address are undefined.
34 /// The `count` argument is in units of T; e.g. a `count` of 3
35 /// represents a pointer offset of `3 * sizeof::<T>()` bytes.
36 #[inline]
37 pub unsafe fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
38     intrinsics::offset(ptr as *T, count) as *mut T
39 }
40
41 /// Return the offset of the first null pointer in `buf`.
42 #[inline]
43 pub unsafe fn buf_len<T>(buf: **T) -> uint {
44     position(buf, |i| *i == null())
45 }
46
47 impl<T> Clone for *T {
48     #[inline]
49     fn clone(&self) -> *T {
50         *self
51     }
52 }
53
54 impl<T> Clone for *mut T {
55     #[inline]
56     fn clone(&self) -> *mut T {
57         *self
58     }
59 }
60
61 /// Return the first offset `i` such that `f(buf[i]) == true`.
62 #[inline]
63 pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
64     let mut i = 0;
65     loop {
66         if f(&(*offset(buf, i as int))) { return i; }
67         else { i += 1; }
68     }
69 }
70
71 /// Create an unsafe null pointer
72 #[inline]
73 pub fn null<T>() -> *T { 0 as *T }
74
75 /// Create an unsafe mutable null pointer
76 #[inline]
77 pub fn mut_null<T>() -> *mut T { 0 as *mut T }
78
79 /// Returns true if the pointer is equal to the null pointer.
80 #[inline]
81 pub fn is_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_null() }
82
83 /// Returns true if the pointer is not equal to the null pointer.
84 #[inline]
85 pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
86
87 /**
88  * Copies data from one location to another.
89  *
90  * Copies `count` elements (not bytes) from `src` to `dst`. The source
91  * and destination may overlap.
92  */
93 #[inline]
94 pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
95     intrinsics::copy_memory(dst, cast::transmute_immut_unsafe(src), count)
96 }
97
98 /**
99  * Copies data from one location to another.
100  *
101  * Copies `count` elements (not bytes) from `src` to `dst`. The source
102  * and destination may *not* overlap.
103  */
104 #[inline]
105 pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
106                                                         src: P,
107                                                         count: uint) {
108     intrinsics::copy_nonoverlapping_memory(dst, cast::transmute_immut_unsafe(src), count)
109 }
110
111 /**
112  * Invokes memset on the specified pointer, setting `count * size_of::<T>()`
113  * bytes of memory starting at `dst` to `c`.
114  */
115 #[inline]
116 pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
117     intrinsics::set_memory(dst, c, count)
118 }
119
120 /**
121  * Zeroes out `count * size_of::<T>` bytes of memory at `dst`
122  */
123 #[inline]
124 pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
125     set_memory(dst, 0, count);
126 }
127
128 /**
129  * Swap the values at two mutable locations of the same type, without
130  * deinitialising or copying either one.
131  */
132 #[inline]
133 pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
134     // Give ourselves some scratch space to work with
135     let mut tmp: T = intrinsics::uninit();
136     let t: *mut T = &mut tmp;
137
138     // Perform the swap
139     copy_nonoverlapping_memory(t, x, 1);
140     copy_memory(x, y, 1); // `x` and `y` may overlap
141     copy_nonoverlapping_memory(y, t, 1);
142
143     // y and t now point to the same thing, but we need to completely forget `tmp`
144     // because it's no longer relevant.
145     cast::forget(tmp);
146 }
147
148 /**
149  * Replace the value at a mutable location with a new one, returning the old
150  * value, without deinitialising or copying either one.
151  */
152 #[inline]
153 pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
154     swap(cast::transmute(dest), &mut src); // cannot overlap
155     src
156 }
157
158 /**
159  * Reads the value from `*src` and returns it. Does not copy `*src`.
160  */
161 #[inline(always)]
162 pub unsafe fn read_ptr<T>(src: *T) -> T {
163     let mut tmp: T = intrinsics::uninit();
164     copy_nonoverlapping_memory(&mut tmp, src, 1);
165     tmp
166 }
167
168 /**
169  * Reads the value from `*src` and nulls it out.
170  * This currently prevents destructors from executing.
171  */
172 #[inline(always)]
173 pub unsafe fn read_and_zero_ptr<T>(dest: *mut T) -> T {
174     // Copy the data out from `dest`:
175     let tmp = read_ptr(&*dest);
176
177     // Now zero out `dest`:
178     zero_memory(dest, 1);
179
180     tmp
181 }
182
183 /// Transform a region pointer - &T - to an unsafe pointer - *T.
184 #[inline]
185 pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
186     thing as *T
187 }
188
189 /// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T.
190 #[inline]
191 pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
192     thing as *mut T
193 }
194
195 /**
196   Given a **T (pointer to an array of pointers),
197   iterate through each *T, up to the provided `len`,
198   passing to the provided callback function
199
200   SAFETY NOTE: Pointer-arithmetic. Dragons be here.
201 */
202 pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
203     debug!("array_each_with_len: before iterate");
204     if (arr as uint == 0) {
205         fail!("ptr::array_each_with_len failure: arr input is null pointer");
206     }
207     //let start_ptr = *arr;
208     for e in range(0, len) {
209         let n = offset(arr, e as int);
210         cb(*n);
211     }
212     debug!("array_each_with_len: after iterate");
213 }
214
215 /**
216   Given a null-pointer-terminated **T (pointer to
217   an array of pointers), iterate through each *T,
218   passing to the provided callback function
219
220   SAFETY NOTE: This will only work with a null-terminated
221   pointer array. Barely less-dodgy Pointer Arithmetic.
222   Dragons be here.
223 */
224 pub unsafe fn array_each<T>(arr: **T, cb: |*T|) {
225     if (arr as uint == 0) {
226         fail!("ptr::array_each_with_len failure: arr input is null pointer");
227     }
228     let len = buf_len(arr);
229     debug!("array_each inferred len: {}", len);
230     array_each_with_len(arr, len, cb);
231 }
232
233 #[allow(missing_doc)]
234 pub trait RawPtr<T> {
235     fn null() -> Self;
236     fn is_null(&self) -> bool;
237     fn is_not_null(&self) -> bool;
238     fn to_uint(&self) -> uint;
239     unsafe fn to_option(&self) -> Option<&T>;
240     unsafe fn offset(self, count: int) -> Self;
241 }
242
243 /// Extension methods for immutable pointers
244 impl<T> RawPtr<T> for *T {
245     /// Returns the null pointer.
246     #[inline]
247     fn null() -> *T { null() }
248
249     /// Returns true if the pointer is equal to the null pointer.
250     #[inline]
251     fn is_null(&self) -> bool { *self == RawPtr::null() }
252
253     /// Returns true if the pointer is not equal to the null pointer.
254     #[inline]
255     fn is_not_null(&self) -> bool { *self != RawPtr::null() }
256
257     /// Returns the address of this pointer.
258     #[inline]
259     fn to_uint(&self) -> uint { *self as uint }
260
261     ///
262     /// Returns `None` if the pointer is null, or else returns the value wrapped
263     /// in `Some`.
264     ///
265     /// # Safety Notes
266     ///
267     /// While this method is useful for null-safety, it is important to note
268     /// that this is still an unsafe operation because the returned value could
269     /// be pointing to invalid memory.
270     ///
271     #[inline]
272     unsafe fn to_option(&self) -> Option<&T> {
273         if self.is_null() { None } else {
274             Some(cast::transmute(*self))
275         }
276     }
277
278     /// Calculates the offset from a pointer. The offset *must* be in-bounds of
279     /// the object, or one-byte-past-the-end.
280     #[inline]
281     unsafe fn offset(self, count: int) -> *T { offset(self, count) }
282 }
283
284 /// Extension methods for mutable pointers
285 impl<T> RawPtr<T> for *mut T {
286     /// Returns the null pointer.
287     #[inline]
288     fn null() -> *mut T { mut_null() }
289
290     /// Returns true if the pointer is equal to the null pointer.
291     #[inline]
292     fn is_null(&self) -> bool { *self == RawPtr::null() }
293
294     /// Returns true if the pointer is not equal to the null pointer.
295     #[inline]
296     fn is_not_null(&self) -> bool { *self != RawPtr::null() }
297
298     /// Returns the address of this pointer.
299     #[inline]
300     fn to_uint(&self) -> uint { *self as uint }
301
302     ///
303     /// Returns `None` if the pointer is null, or else returns the value wrapped
304     /// in `Some`.
305     ///
306     /// # Safety Notes
307     ///
308     /// While this method is useful for null-safety, it is important to note
309     /// that this is still an unsafe operation because the returned value could
310     /// be pointing to invalid memory.
311     ///
312     #[inline]
313     unsafe fn to_option(&self) -> Option<&T> {
314         if self.is_null() { None } else {
315             Some(cast::transmute(*self))
316         }
317     }
318
319     /// Calculates the offset from a pointer. The offset *must* be in-bounds of
320     /// the object, or one-byte-past-the-end. An arithmetic overflow is also
321     /// undefined behaviour.
322     ///
323     /// This method should be preferred over `offset` when the guarantee can be
324     /// satisfied, to enable better optimization.
325     #[inline]
326     unsafe fn offset(self, count: int) -> *mut T { mut_offset(self, count) }
327 }
328
329 // Equality for pointers
330 #[cfg(not(test))]
331 impl<T> Eq for *T {
332     #[inline]
333     fn eq(&self, other: &*T) -> bool {
334         *self == *other
335     }
336     #[inline]
337     fn ne(&self, other: &*T) -> bool { !self.eq(other) }
338 }
339
340 #[cfg(not(test))]
341 impl<T> Eq for *mut T {
342     #[inline]
343     fn eq(&self, other: &*mut T) -> bool {
344         *self == *other
345     }
346     #[inline]
347     fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
348 }
349
350 // Equivalence for pointers
351 #[cfg(not(test))]
352 impl<T> Equiv<*mut T> for *T {
353     fn equiv(&self, other: &*mut T) -> bool {
354         self.to_uint() == other.to_uint()
355     }
356 }
357
358 #[cfg(not(test))]
359 impl<T> Equiv<*T> for *mut T {
360     fn equiv(&self, other: &*T) -> bool {
361         self.to_uint() == other.to_uint()
362     }
363 }
364
365 // Equality for extern "C" fn pointers
366 #[cfg(not(test))]
367 mod externfnpointers {
368     use cast;
369     use cmp::Eq;
370
371     impl<_R> Eq for extern "C" fn() -> _R {
372         #[inline]
373         fn eq(&self, other: &extern "C" fn() -> _R) -> bool {
374             let self_: *() = unsafe { cast::transmute(*self) };
375             let other_: *() = unsafe { cast::transmute(*other) };
376             self_ == other_
377         }
378         #[inline]
379         fn ne(&self, other: &extern "C" fn() -> _R) -> bool {
380             !self.eq(other)
381         }
382     }
383     macro_rules! fnptreq(
384         ($($p:ident),*) => {
385             impl<_R,$($p),*> Eq for extern "C" fn($($p),*) -> _R {
386                 #[inline]
387                 fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
388                     let self_: *() = unsafe { cast::transmute(*self) };
389                     let other_: *() = unsafe { cast::transmute(*other) };
390                     self_ == other_
391                 }
392                 #[inline]
393                 fn ne(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
394                     !self.eq(other)
395                 }
396             }
397         }
398     )
399     fnptreq!(A)
400     fnptreq!(A,B)
401     fnptreq!(A,B,C)
402     fnptreq!(A,B,C,D)
403     fnptreq!(A,B,C,D,E)
404 }
405
406 // Comparison for pointers
407 #[cfg(not(test))]
408 impl<T> Ord for *T {
409     #[inline]
410     fn lt(&self, other: &*T) -> bool {
411         *self < *other
412     }
413     #[inline]
414     fn le(&self, other: &*T) -> bool {
415         *self <= *other
416     }
417     #[inline]
418     fn ge(&self, other: &*T) -> bool {
419         *self >= *other
420     }
421     #[inline]
422     fn gt(&self, other: &*T) -> bool {
423         *self > *other
424     }
425 }
426
427 #[cfg(not(test))]
428 impl<T> Ord for *mut T {
429     #[inline]
430     fn lt(&self, other: &*mut T) -> bool {
431         *self < *other
432     }
433     #[inline]
434     fn le(&self, other: &*mut T) -> bool {
435         *self <= *other
436     }
437     #[inline]
438     fn ge(&self, other: &*mut T) -> bool {
439         *self >= *other
440     }
441     #[inline]
442     fn gt(&self, other: &*mut T) -> bool {
443         *self > *other
444     }
445 }
446
447 #[cfg(test)]
448 pub mod ptr_tests {
449     use super::*;
450     use prelude::*;
451
452     use c_str::ToCStr;
453     use cast;
454     use libc;
455     use str;
456     use vec::{ImmutableVector, MutableVector};
457
458     #[test]
459     fn test() {
460         unsafe {
461             struct Pair {
462                 fst: int,
463                 snd: int
464             };
465             let mut p = Pair {fst: 10, snd: 20};
466             let pptr: *mut Pair = &mut p;
467             let iptr: *mut int = cast::transmute(pptr);
468             assert_eq!(*iptr, 10);
469             *iptr = 30;
470             assert_eq!(*iptr, 30);
471             assert_eq!(p.fst, 30);
472
473             *pptr = Pair {fst: 50, snd: 60};
474             assert_eq!(*iptr, 50);
475             assert_eq!(p.fst, 50);
476             assert_eq!(p.snd, 60);
477
478             let v0 = ~[32000u16, 32001u16, 32002u16];
479             let mut v1 = ~[0u16, 0u16, 0u16];
480
481             copy_memory(mut_offset(v1.as_mut_ptr(), 1),
482                         offset(v0.as_ptr(), 1), 1);
483             assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
484             copy_memory(v1.as_mut_ptr(),
485                         offset(v0.as_ptr(), 2), 1);
486             assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
487                      v1[2] == 0u16));
488             copy_memory(mut_offset(v1.as_mut_ptr(), 2),
489                         v0.as_ptr(), 1u);
490             assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
491                      v1[2] == 32000u16));
492         }
493     }
494
495     #[test]
496     fn test_position() {
497         use libc::c_char;
498
499         "hello".with_c_str(|p| {
500             unsafe {
501                 assert!(2u == position(p, |c| *c == 'l' as c_char));
502                 assert!(4u == position(p, |c| *c == 'o' as c_char));
503                 assert!(5u == position(p, |c| *c == 0 as c_char));
504             }
505         })
506     }
507
508     #[test]
509     fn test_buf_len() {
510         "hello".with_c_str(|p0| {
511             "there".with_c_str(|p1| {
512                 "thing".with_c_str(|p2| {
513                     let v = ~[p0, p1, p2, null()];
514                     unsafe {
515                         assert_eq!(buf_len(v.as_ptr()), 3u);
516                     }
517                 })
518             })
519         })
520     }
521
522     #[test]
523     fn test_is_null() {
524         let p: *int = null();
525         assert!(p.is_null());
526         assert!(!p.is_not_null());
527
528         let q = unsafe { offset(p, 1) };
529         assert!(!q.is_null());
530         assert!(q.is_not_null());
531
532         let mp: *mut int = mut_null();
533         assert!(mp.is_null());
534         assert!(!mp.is_not_null());
535
536         let mq = unsafe { mp.offset(1) };
537         assert!(!mq.is_null());
538         assert!(mq.is_not_null());
539     }
540
541     #[test]
542     fn test_to_option() {
543         unsafe {
544             let p: *int = null();
545             assert_eq!(p.to_option(), None);
546
547             let q: *int = &2;
548             assert_eq!(q.to_option().unwrap(), &2);
549
550             let p: *mut int = mut_null();
551             assert_eq!(p.to_option(), None);
552
553             let q: *mut int = &mut 2;
554             assert_eq!(q.to_option().unwrap(), &2);
555         }
556     }
557
558     #[test]
559     fn test_ptr_addition() {
560         use vec::raw::*;
561
562         unsafe {
563             let xs = ~[5, ..16];
564             let mut ptr = xs.as_ptr();
565             let end = ptr.offset(16);
566
567             while ptr < end {
568                 assert_eq!(*ptr, 5);
569                 ptr = ptr.offset(1);
570             }
571
572             let mut xs_mut = xs.clone();
573             let mut m_ptr = xs_mut.as_mut_ptr();
574             let m_end = m_ptr.offset(16);
575
576             while m_ptr < m_end {
577                 *m_ptr += 5;
578                 m_ptr = m_ptr.offset(1);
579             }
580
581             assert_eq!(xs_mut, ~[10, ..16]);
582         }
583     }
584
585     #[test]
586     fn test_ptr_subtraction() {
587         unsafe {
588             let xs = ~[0,1,2,3,4,5,6,7,8,9];
589             let mut idx = 9i8;
590             let ptr = xs.as_ptr();
591
592             while idx >= 0i8 {
593                 assert_eq!(*(ptr.offset(idx as int)), idx as int);
594                 idx = idx - 1i8;
595             }
596
597             let mut xs_mut = xs.clone();
598             let m_start = xs_mut.as_mut_ptr();
599             let mut m_ptr = m_start.offset(9);
600
601             while m_ptr >= m_start {
602                 *m_ptr += *m_ptr;
603                 m_ptr = m_ptr.offset(-1);
604             }
605
606             assert_eq!(xs_mut, ~[0,2,4,6,8,10,12,14,16,18]);
607         }
608     }
609
610     #[test]
611     fn test_ptr_array_each_with_len() {
612         unsafe {
613             let one = "oneOne".to_c_str();
614             let two = "twoTwo".to_c_str();
615             let three = "threeThree".to_c_str();
616             let arr = ~[
617                 one.with_ref(|buf| buf),
618                 two.with_ref(|buf| buf),
619                 three.with_ref(|buf| buf),
620             ];
621             let expected_arr = [
622                 one, two, three
623             ];
624
625             let mut ctr = 0;
626             let mut iteration_count = 0;
627             array_each_with_len(arr.as_ptr(), arr.len(), |e| {
628                     let actual = str::raw::from_c_str(e);
629                     let expected = expected_arr[ctr].with_ref(|buf| {
630                             str::raw::from_c_str(buf)
631                         });
632                     debug!(
633                         "test_ptr_array_each_with_len e: {}, a: {}",
634                         expected, actual);
635                     assert_eq!(actual, expected);
636                     ctr += 1;
637                     iteration_count += 1;
638                 });
639             assert_eq!(iteration_count, 3u);
640         }
641     }
642
643     #[test]
644     fn test_ptr_array_each() {
645         unsafe {
646             let one = "oneOne".to_c_str();
647             let two = "twoTwo".to_c_str();
648             let three = "threeThree".to_c_str();
649             let arr = ~[
650                 one.with_ref(|buf| buf),
651                 two.with_ref(|buf| buf),
652                 three.with_ref(|buf| buf),
653                 // fake a null terminator
654                 null(),
655             ];
656             let expected_arr = [
657                 one, two, three
658             ];
659
660             let arr_ptr = arr.as_ptr();
661             let mut ctr = 0;
662             let mut iteration_count = 0;
663             array_each(arr_ptr, |e| {
664                     let actual = str::raw::from_c_str(e);
665                     let expected = expected_arr[ctr].with_ref(|buf| {
666                         str::raw::from_c_str(buf)
667                     });
668                     debug!(
669                         "test_ptr_array_each e: {}, a: {}",
670                         expected, actual);
671                     assert_eq!(actual, expected);
672                     ctr += 1;
673                     iteration_count += 1;
674                 });
675             assert_eq!(iteration_count, 3);
676         }
677     }
678
679     #[test]
680     #[should_fail]
681     fn test_ptr_array_each_with_len_null_ptr() {
682         unsafe {
683             array_each_with_len(0 as **libc::c_char, 1, |e| {
684                 str::raw::from_c_str(e);
685             });
686         }
687     }
688     #[test]
689     #[should_fail]
690     fn test_ptr_array_each_null_ptr() {
691         unsafe {
692             array_each(0 as **libc::c_char, |e| {
693                 str::raw::from_c_str(e);
694             });
695         }
696     }
697
698     #[test]
699     fn test_set_memory() {
700         let mut xs = [0u8, ..20];
701         let ptr = xs.as_mut_ptr();
702         unsafe { set_memory(ptr, 5u8, xs.len()); }
703         assert_eq!(xs, [5u8, ..20]);
704     }
705 }