]> git.lizzy.rs Git - rust.git/blob - src/libcore/should_not_exist.rs
add an align parameter to exchange_malloc
[rust.git] / src / libcore / should_not_exist.rs
1 // Copyright 2014 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 use cast;
12 use char::Char;
13 use clone::Clone;
14 use container::Container;
15 use default::Default;
16 use finally::try_finally;
17 use intrinsics;
18 use iter::{range, Iterator, FromIterator};
19 use mem;
20 use num::{CheckedMul, CheckedAdd};
21 use option::{Some, None};
22 use ptr::RawPtr;
23 use ptr;
24 use raw::Vec;
25 use slice::ImmutableVector;
26 use str::StrSlice;
27
28 #[cfg(not(test))] use ops::Add;
29
30 #[allow(ctypes)]
31 extern {
32     #[cfg(stage0)]
33     fn rust_malloc(size: uint) -> *u8;
34     #[cfg(not(stage0))]
35     fn rust_malloc(size: uint, align: uint) -> *u8;
36     fn rust_free(ptr: *u8);
37 }
38
39 #[cfg(stage0)]
40 unsafe fn alloc(cap: uint) -> *mut Vec<()> {
41     let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
42     let ret = rust_malloc(cap) as *mut Vec<()>;
43     if ret.is_null() {
44         intrinsics::abort();
45     }
46     (*ret).fill = 0;
47     (*ret).alloc = cap;
48     ret
49 }
50
51 #[cfg(not(stage0))]
52 unsafe fn alloc(cap: uint) -> *mut Vec<()> {
53     let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
54     let ret = rust_malloc(cap, 8) as *mut Vec<()>;
55     if ret.is_null() {
56         intrinsics::abort();
57     }
58     (*ret).fill = 0;
59     (*ret).alloc = cap;
60     ret
61 }
62
63 // Strings
64
65 impl Default for ~str {
66     fn default() -> ~str {
67         unsafe {
68             // Get some memory
69             let ptr = alloc(0);
70
71             // Initialize the memory
72             (*ptr).fill = 0;
73             (*ptr).alloc = 0;
74
75             cast::transmute(ptr)
76         }
77     }
78 }
79
80 impl Clone for ~str {
81     fn clone(&self) -> ~str {
82         // Don't use the clone() implementation above because it'll start
83         // requiring the eh_personality lang item (no fun)
84         unsafe {
85             let bytes = self.as_bytes().as_ptr();
86             let len = self.len();
87
88             let ptr = alloc(len) as *mut Vec<u8>;
89             ptr::copy_nonoverlapping_memory(&mut (*ptr).data, bytes, len);
90             (*ptr).fill = len;
91             (*ptr).alloc = len;
92
93             cast::transmute(ptr)
94         }
95     }
96 }
97
98 impl FromIterator<char> for ~str {
99     #[inline]
100     fn from_iter<T: Iterator<char>>(mut iterator: T) -> ~str {
101         let (lower, _) = iterator.size_hint();
102         let mut cap = if lower == 0 {16} else {lower};
103         let mut len = 0;
104         let mut tmp = [0u8, ..4];
105
106         unsafe {
107             let mut ptr = alloc(cap) as *mut Vec<u8>;
108             let mut ret = cast::transmute(ptr);
109             for ch in iterator {
110                 let amt = ch.encode_utf8(tmp);
111
112                 if len + amt > cap {
113                     cap = cap.checked_mul(&2).unwrap();
114                     if cap < len + amt {
115                         cap = len + amt;
116                     }
117                     let ptr2 = alloc(cap) as *mut Vec<u8>;
118                     ptr::copy_nonoverlapping_memory(&mut (*ptr2).data,
119                                                     &(*ptr).data,
120                                                     len);
121                     rust_free(ptr as *u8);
122                     cast::forget(ret);
123                     ret = cast::transmute(ptr2);
124                     ptr = ptr2;
125                 }
126
127                 let base = &mut (*ptr).data as *mut u8;
128                 for byte in tmp.slice_to(amt).iter() {
129                     *base.offset(len as int) = *byte;
130                     len += 1;
131                 }
132                 (*ptr).fill = len;
133             }
134             ret
135         }
136     }
137 }
138
139 #[cfg(not(test))]
140 impl<'a> Add<&'a str,~str> for &'a str {
141     #[inline]
142     fn add(&self, rhs: & &'a str) -> ~str {
143         let amt = self.len().checked_add(&rhs.len()).unwrap();
144         unsafe {
145             let ptr = alloc(amt) as *mut Vec<u8>;
146             let base = &mut (*ptr).data as *mut _;
147             ptr::copy_nonoverlapping_memory(base,
148                                             self.as_bytes().as_ptr(),
149                                             self.len());
150             let base = base.offset(self.len() as int);
151             ptr::copy_nonoverlapping_memory(base,
152                                             rhs.as_bytes().as_ptr(),
153                                             rhs.len());
154             (*ptr).fill = amt;
155             (*ptr).alloc = amt;
156             cast::transmute(ptr)
157         }
158     }
159 }
160
161 // Arrays
162
163 impl<A: Clone> Clone for ~[A] {
164     #[inline]
165     fn clone(&self) -> ~[A] {
166         let len = self.len();
167         let data_size = len.checked_mul(&mem::size_of::<A>()).unwrap();
168         let size = mem::size_of::<Vec<()>>().checked_add(&data_size).unwrap();
169
170         unsafe {
171             let ret = alloc(size) as *mut Vec<A>;
172
173             (*ret).fill = len * mem::nonzero_size_of::<A>();
174             (*ret).alloc = len * mem::nonzero_size_of::<A>();
175
176             let mut i = 0;
177             let p = &mut (*ret).data as *mut _ as *mut A;
178             try_finally(
179                 &mut i, (),
180                 |i, ()| while *i < len {
181                     mem::move_val_init(
182                         &mut(*p.offset(*i as int)),
183                         self.unsafe_ref(*i).clone());
184                     *i += 1;
185                 },
186                 |i| if *i < len {
187                     // we must be failing, clean up after ourselves
188                     for j in range(0, *i as int) {
189                         ptr::read(&*p.offset(j));
190                     }
191                     rust_free(ret as *u8);
192                 });
193             cast::transmute(ret)
194         }
195     }
196 }