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 fn malloc(size: uint) -> *u8;
33 fn free(ptr: *u8);
34 }
35
36 unsafe fn alloc(cap: uint) -> *mut Vec<()> {
37 let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
38 let ret = malloc(cap) as *mut Vec<()>;
39 if ret.is_null() {
40 intrinsics::abort();
41 }
42 (*ret).fill = 0;
43 (*ret).alloc = cap;
44 ret
45 }
46
47 // Strings
48
49 impl Default for ~str {
50 fn default() -> ~str {
51 unsafe {
52 // Get some memory
53 let ptr = alloc(0);
54
55 // Initialize the memory
56 (*ptr).fill = 0;
57 (*ptr).alloc = 0;
58
59 cast::transmute(ptr)
60 }
61 }
62 }
63
64 impl Clone for ~str {
65 fn clone(&self) -> ~str {
66 // Don't use the clone() implementation above because it'll start
67 // requiring the eh_personality lang item (no fun)
68 unsafe {
69 let bytes = self.as_bytes().as_ptr();
70 let len = self.len();
71
72 let ptr = alloc(len) as *mut Vec<u8>;
73 ptr::copy_nonoverlapping_memory(&mut (*ptr).data, bytes, len);
74 (*ptr).fill = len;
75 (*ptr).alloc = len;
76
77 cast::transmute(ptr)
78 }
79 }
80 }
81
82 impl FromIterator<char> for ~str {
83 #[inline]
84 fn from_iter<T: Iterator<char>>(mut iterator: T) -> ~str {
85 let (lower, _) = iterator.size_hint();
86 let mut cap = if lower == 0 {16} else {lower};
87 let mut len = 0;
88 let mut tmp = [0u8, ..4];
89
90 unsafe {
91 let mut ptr = alloc(cap) as *mut Vec<u8>;
92 let mut ret = cast::transmute(ptr);
93 for ch in iterator {
94 let amt = ch.encode_utf8(tmp);
95
96 if len + amt > cap {
97 cap = cap.checked_mul(&2).unwrap();
98 if cap < len + amt {
99 cap = len + amt;
100 }
101 let ptr2 = alloc(cap) as *mut Vec<u8>;
102 ptr::copy_nonoverlapping_memory(&mut (*ptr2).data,
103 &(*ptr).data,
104 len);
105 free(ptr as *u8);
106 cast::forget(ret);
107 ret = cast::transmute(ptr2);
108 ptr = ptr2;
109 }
110
111 let base = &mut (*ptr).data as *mut u8;
112 for byte in tmp.slice_to(amt).iter() {
113 *base.offset(len as int) = *byte;
114 len += 1;
115 }
116 (*ptr).fill = len;
117 }
118 ret
119 }
120 }
121 }
122
123 #[cfg(not(test))]
124 impl<'a> Add<&'a str,~str> for &'a str {
125 #[inline]
126 fn add(&self, rhs: & &'a str) -> ~str {
127 let amt = self.len().checked_add(&rhs.len()).unwrap();
128 unsafe {
129 let ptr = alloc(amt) as *mut Vec<u8>;
130 let base = &mut (*ptr).data as *mut _;
131 ptr::copy_nonoverlapping_memory(base,
132 self.as_bytes().as_ptr(),
133 self.len());
134 let base = base.offset(self.len() as int);
135 ptr::copy_nonoverlapping_memory(base,
136 rhs.as_bytes().as_ptr(),
137 rhs.len());
138 (*ptr).fill = amt;
139 (*ptr).alloc = amt;
140 cast::transmute(ptr)
141 }
142 }
143 }
144
145 // Arrays
146
147 impl<A: Clone> Clone for ~[A] {
148 #[inline]
149 fn clone(&self) -> ~[A] {
150 let len = self.len();
151 let data_size = len.checked_mul(&mem::size_of::<A>()).unwrap();
152 let size = mem::size_of::<Vec<()>>().checked_add(&data_size).unwrap();
153
154 unsafe {
155 let ret = alloc(size) as *mut Vec<A>;
156
157 (*ret).fill = len * mem::nonzero_size_of::<A>();
158 (*ret).alloc = len * mem::nonzero_size_of::<A>();
159
160 let mut i = 0;
161 let p = &mut (*ret).data as *mut _ as *mut A;
162 try_finally(
163 &mut i, (),
164 |i, ()| while *i < len {
165 mem::move_val_init(
166 &mut(*p.offset(*i as int)),
167 self.unsafe_ref(*i).clone());
168 *i += 1;
169 },
170 |i| if *i < len {
171 // we must be failing, clean up after ourselves
172 for j in range(0, *i as int) {
173 ptr::read(&*p.offset(j));
174 }
175 free(ret as *u8);
176 });
177 cast::transmute(ret)
178 }
179 }
180 }