1extern crate libc;
9
10
11use std::{fmt, mem};
12use std::ops::{Drop, Range};
13
14
15const CHUNK_SIZE: isize = 32;
16
17
18pub struct GapBuffer {
21 buf_start: *mut u8,
22 gap_start: *mut u8,
23 gap_end: *mut u8,
24 buf_end: *mut u8
25}
26
27impl GapBuffer {
28 pub fn insert_str(&mut self, offset: usize, s: &str) {
30 let s_len = s.len() as isize;
31 if s_len > self.gap_len() {
32 self.grow_gap(s_len);
33 }
34
35 self.move_gap_to(offset as isize);
36
37 let src_ptr = s.as_bytes().as_ptr();
38 unsafe {
39 libc::memcpy(self.gap_start as *mut libc::c_void,
40 src_ptr as *const libc::c_void,
41 s_len as usize);
42 self.gap_start = self.gap_start.offset(s_len);
43 }
44 }
45
46 pub fn remove(&mut self, range: Range<usize>) {
48 let buf_len = self.buf_len() as usize;
49 assert!(range.start < range.end, "Invalid range: {:?}", range);
50 assert!(range.start < buf_len);
51 assert!(range.end <= buf_len);
52
53 let s = self.to_string();
54 let head = &s[0..range.start];
55 let tail = &s[range.end..];
56
57 self.clear();
58 self.insert_str(0, &head);
59 self.insert_str(head.len(), &tail);
60 }
61
62 pub fn with_capacity(capacity: usize) -> GapBuffer {
68 let buffer = unsafe {
69 let size = mem::size_of::<u8>() * capacity;
70 libc::malloc(size) as *mut u8
71 };
72
73 if buffer.is_null() && capacity != 0 {
75 panic!("Unable to allocate requested capacity");
76 }
77
78 GapBuffer {
79 buf_start: buffer,
80 gap_start: buffer,
81 gap_end: unsafe { buffer.offset(capacity as isize) },
82 buf_end: unsafe { buffer.offset(capacity as isize) }
83 }
84 }
85
86 fn allocate_extra(&mut self, extra: isize) {
87 let current_size = ptr_diff(self.buf_end, self.buf_start);
88 let new_size = mem::size_of::<u8>()
89 * extra as usize
90 + current_size as usize;
91
92 let new_buf = unsafe {
93 libc::realloc(self.buf_start as *mut libc::c_void,
94 new_size) as *mut u8
95 };
96
97 assert!(!new_buf.is_null(), "Out of memory");
98
99 self.buf_start = new_buf;
100 }
101
102 fn buf_len(&self) -> isize {
103 let head_len = ptr_diff(self.gap_start, self.buf_start);
104 let tail_len = ptr_diff(self.buf_end, self.gap_end);
105 head_len + tail_len
106 }
107
108 fn clear(&mut self) {
109 self.gap_start = self.buf_start;
110 self.gap_end = self.buf_end;
111 }
112
113 fn gap_len(&self) -> isize {
114 ptr_diff(self.gap_end, self.gap_start)
115 }
116
117 fn grow_gap(&mut self, size: isize) {
118 let available = self.gap_len();
119 let needed = size - available;
120
121 let mut chunk = (needed as f32 / CHUNK_SIZE as f32).ceil() as isize;
122 chunk *= CHUNK_SIZE;
123
124 let head_len = ptr_diff(self.gap_start, self.buf_start);
125 let tail_len = ptr_diff(self.buf_end, self.gap_end);
126 let new_gap_size = self.gap_len() + chunk;
127 let buf_len = head_len + tail_len;
128
129 self.allocate_extra(chunk);
130 unsafe {
131 libc::memmove(self.gap_start as *mut libc::c_void,
132 self.gap_end as *const libc::c_void,
133 tail_len as usize);
134 self.gap_start = self.buf_start.offset(buf_len);
135 self.gap_end = self.gap_start.offset(new_gap_size);
136 self.buf_end = self.gap_end;
137 }
138 }
139
140 fn head(&self) -> String {
141 let head_len = ptr_diff(self.gap_start, self.buf_start) as usize;
142 string_from_segment(self.buf_start, head_len)
143 }
144
145 fn move_gap_to(&mut self, offset: isize) {
146 let gap_len = self.gap_len();
147 let new_pos = unsafe { self.buf_start.offset(offset) };
148
149 let diff = ptr_diff(new_pos, self.gap_start);
150
151 if diff == 0 { return; }
152
153 if diff < 0 {
154 unsafe {
155 self.gap_start = new_pos;
156 self.gap_end = self.gap_start.offset(gap_len);
157 libc::memmove(self.gap_end as *mut libc::c_void,
158 self.gap_start as *mut libc::c_void,
159 diff.abs() as usize);
160 }
161 } else {
162 unsafe {
163 self.gap_end = self.gap_end.offset(diff);
164 self.gap_start = self.gap_start.offset(diff);
165 libc::memmove(new_pos as *mut libc::c_void,
166 self.gap_start as *mut libc::c_void,
167 diff as usize);
168 }
169 }
170 }
171
172 fn tail(&self) -> String {
173 let tail_len = ptr_diff(self.buf_end, self.gap_end) as usize;
174 string_from_segment(self.gap_end, tail_len)
175 }
176}
177
178impl fmt::Display for GapBuffer {
179 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180 write!(f, "{}{}", self.head(), self.tail())
181 }
182}
183
184impl Drop for GapBuffer {
185 fn drop(&mut self) {
186 unsafe { libc::free(self.buf_start as *mut libc::c_void); }
187 }
188}
189
190fn ptr_to_isize(p: *const u8) -> isize {
191 unsafe { mem::transmute::<*const u8, isize>(p) }
192}
193
194fn ptr_diff(p: *const u8, q: *const u8) -> isize {
195 ptr_to_isize(p) - ptr_to_isize(q)
196}
197
198fn string_from_segment(start: *mut u8, len: usize) -> String {
199 let mut s = String::with_capacity(len);
200 let tmp = unsafe { String::from_raw_parts(start, len, len) };
201 s.push_str(&tmp);
202 mem::forget(tmp);
203 s
204}
205
206
207#[cfg(test)]
208mod tests {
209 use super::GapBuffer;
210
211
212 #[test]
213 fn insert_str_1() {
214 let gap_buf = buf_from_str("12345678");
215 let text = gap_buf.to_string();
216 assert!(text == "12345678");
217 }
218
219 #[test]
220 fn insert_str_2() {
221 let mut gap_buf = buf_from_str("12345678");
222 gap_buf.insert_str(7, "9");
223
224 let text = gap_buf.to_string();
225 assert!(text == "123456798");
226 }
227
228 #[test]
229 fn insert_str_3() {
230 let mut gap_buf = buf_from_str("12345678");
231 gap_buf.insert_str(0, "0");
232
233 let text = gap_buf.to_string();
234 assert!(text == "012345678");
235 }
236
237 #[test]
238 fn insert_str_4() {
239 let mut gap_buf = buf_from_str("0123456789.0123456789.0123456789");
240 gap_buf.insert_str(0, "9876543210.");
241
242 let text = gap_buf.to_string();
243 assert!(text == "9876543210.0123456789.0123456789.0123456789");
244 }
245
246 #[test]
247 fn insert_str_5() {
248 let mut gap_buf = buf_from_str("0123456789.0123456789.0123456789");
249 gap_buf.insert_str(11, "9876543210.");
250
251 let text = gap_buf.to_string();
252 assert!(text == "0123456789.9876543210.0123456789.0123456789");
253 }
254
255 #[test]
256 fn remove_1() {
257 let mut gap_buf = buf_from_str("12345678");
258 gap_buf.remove(0..8);
259
260 let text = gap_buf.to_string();
261 assert!(text == "");
262 }
263
264 #[test]
265 fn remove_2() {
266 let mut gap_buf = buf_from_str("12345678");
267 gap_buf.remove(0..1);
268
269 let text = gap_buf.to_string();
270 assert!(text == "2345678");
271 }
272
273 #[test]
274 fn remove_3() {
275 let mut gap_buf = buf_from_str("12345678");
276 gap_buf.remove(7..8);
277
278 let text = gap_buf.to_string();
279 assert!(text == "1234567");
280 }
281
282 #[test]
283 fn remove_4() {
284 let mut gap_buf = buf_from_str("12345678");
285 gap_buf.remove(3..6);
286
287 let text = gap_buf.to_string();
288 assert!(text == "12378");
289 }
290
291 #[test]
292 #[should_panic]
293 fn remove_5() {
294 let mut gap_buf = buf_from_str("12345678");
295 gap_buf.remove(0..9);
296 }
297
298 fn buf_from_str(s: &str) -> GapBuffer {
299 let mut buf = GapBuffer::with_capacity(s.len());
300 buf.insert_str(0, s);
301 buf
302 }
303}