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