gapbuffer/
lib.rs

1//  Copyright 2014 David Lee Aronson.
2//
3//  This program is free software: you can redistribute it and/or modify it under the terms of the
4//  GNU Lesser General Public License as published by the Free Software Foundation, either version 3
5//  of the License, or (at your option) any later version.
6//
7//  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9//  the GNU Lesser General Public License for more details.
10//
11//  You should have received a copy of the GNU Lesser General Public License along with this
12//  program.  If not, see <http://www.gnu.org/licenses/>.
13use std::collections::VecDeque;
14use std::iter::{IntoIterator, FromIterator};
15use std::cmp::Ordering;
16use std::fmt;
17use std::ops::{Index, IndexMut};
18
19/// A GapBuffer is a dynamic array which implements methods to shift the empty portion of the
20/// array around so that modifications can occur at any point in the array. It is optimized for
21/// data structures in which insertions and deletions tend to occur in sequence within the same
22/// area of the array, such as a buffer for a text editor.
23#[derive(Clone,Default)]
24pub struct GapBuffer<T> {
25    /// The start offset of the ring buffer.  This is necessary in order to prevent leftward
26    /// motion from wrapping around from the conceptual front of the buffer to the back (or vice
27    /// versa).
28    offset: usize,
29    /// The backing ring buffer.  Pushing onto the back is considered to insert a character
30    /// into the leftmost empty slot in the gap, while popping from the front is considered
31    /// deleting the leftmost nonempty slot after the gap.  Moving the gap right means cycling the
32    /// first element to the back; moving left means cycling the last element to the front.
33    buf: VecDeque<T>,
34}
35
36impl<T> GapBuffer<T> {
37    ///Constructs an empty GapBuffer.
38    pub fn new() -> GapBuffer<T> {
39        GapBuffer {
40            buf: VecDeque::new(),
41            offset: 0,
42        }
43    }
44
45    ///Constructs a GapBuffer with a given initial capacity.
46    pub fn with_capacity(n: usize) -> GapBuffer<T> {
47        GapBuffer {
48            buf: VecDeque::with_capacity(n),
49            offset: 0,
50        }
51    }
52
53    fn get_idx(&self, i: usize) -> usize {
54        if i < self.offset {
55            // Left of cursor, so indexing starts at self.len() - offset.
56            // Note the order: (self.len() - offset) should be evaluated first, since it is
57            // guaranteed to be nonnegative, and then i should be added (it cannot exceed
58            // self.len() since i < offset, hence it cannot overflow).
59            (self.len() - self.offset) + i
60        } else if i < self.len() {
61            // At or right of cursor, subtract offset.
62            i - self.offset
63        } else {
64            // i out of bounds--leave it that way.
65            i
66        }
67    }
68
69
70    /// Shift the gap in the gap buffer.  Note: does not perform bounds checks.
71    fn shift(&mut self, i: usize) {
72        // Since the caller should have checked bounds already, unwrap() in this function should
73        // never fail.
74        match i.cmp(&self.offset) {
75            // Already at the correct position, don't do anything
76            Ordering::Equal => return,
77            // Need to move left
78            Ordering::Less => {
79                // Moving left means cycling the last element to the front.
80                let mut last = self.buf.pop_back().unwrap();
81                self.offset -= 1;
82                while i < self.offset {
83                    self.buf.push_front(last);
84                    last = self.buf.pop_back().unwrap();
85                    self.offset -= 1;
86                }
87                self.buf.push_front(last);
88            },
89            // Need to move right
90            Ordering::Greater => {
91                // Moving right means cycling the first element to the back.
92                let mut first = self.buf.pop_front().unwrap();
93                self.offset += 1;
94                while i > self.offset {
95                    self.buf.push_back(first);
96                    first = self.buf.pop_front().unwrap();
97                    self.offset += 1;
98                }
99                self.buf.push_back(first);
100            }
101        }
102    }
103
104    ///Get a reference to the element at the index.
105    pub fn get(&self, i: usize) -> Option<&T> {
106        let i = self.get_idx(i);
107        self.buf.get(i)
108    }
109
110    ///Get a mutable reference to the element at the index.
111    pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
112        let i = self.get_idx(i);
113        self.buf.get_mut(i)
114    }
115
116    /// Swap the elements at the index.
117    /// i and j may be equal.
118    ///
119    /// Panics if there is no element with either index.
120    pub fn swap(&mut self, i: usize, j: usize) {
121        let i = self.get_idx(i);
122        let j = self.get_idx(j);
123        self.buf.swap(i, j);
124    }
125
126    ///Get the capacity of the GapBuffer without expanding.
127    #[inline]
128    pub fn capacity(&self) -> usize { self.buf.capacity() }
129
130    /// Reserve at least this much additional space for the GapBuffer.
131    /// The collection may reserve more space to avoid frequent reallocations.
132    ///
133    /// Panics if the new capacity overflows uint.
134    pub fn reserve(&mut self, additional: usize) {
135        self.buf.reserve(additional)
136    }
137
138    ///Get an iterator of this GapBuffer.
139    pub fn iter(&self) -> Items<T> {
140        Items {
141            buff: self,
142            idx: 0,
143        }
144    }
145
146    ///Get the length of the GapBuffer.
147    pub fn len(&self) -> usize { self.buf.len() }
148
149    ///Is the GapBuffer empty?
150    pub fn is_empty(&self) -> bool { self.len() == 0 }
151
152    ///Clears the buffer, removing all values.
153    pub fn clear(&mut self) {
154        self.offset = 0;
155        self.buf.clear();
156    }
157
158    /// Insert a new T at a given index (the gap will be shifted to that index).
159    ///
160    /// Panics if i is greater than VecDeque's length.
161    pub fn insert(&mut self, i: usize, t: T) {
162        // Valid indices: [0, len]
163        assert!(i <= self.len(), "index out of bounds");
164        // Gap is just before index i
165        self.shift(i);
166        // push_back inserts into the leftmost empty slot in the gap.
167        self.offset += 1;
168        self.buf.push_back(t);
169    }
170
171    /// Removes and returns the element at position i from the gap buffer.  The gap will be shifted
172    /// to just before the index.  Returns None if i is out of bounds.
173    pub fn remove(&mut self, i: usize) -> Option<T> {
174        // Valid indices: [0, len)
175        if self.len() <= i {
176            return None;
177        }
178        self.shift(i); // Gap is just before index i
179        // pop_front removes from the rightmost empty slot after the gap.
180        self.buf.pop_front()
181    }
182}
183
184//Eq & PartialEq
185impl <A, B> PartialEq<GapBuffer<B>> for GapBuffer<A> where A: PartialEq<B> {
186    #[inline]
187    fn eq(&self, other: &GapBuffer<B>) -> bool {
188        if self.len() != other.len() { return false }
189        // This isn't as efficient as it could be...
190        self.iter().zip(other.iter()).all( |(x, y)| x == y )
191    }
192}
193
194impl<A> Eq for GapBuffer<A> where A: Eq {}
195
196//Ord & PartialOrd
197impl<A> PartialOrd for GapBuffer<A> where A: PartialOrd {
198    #[inline]
199    fn partial_cmp(&self, other: &GapBuffer<A>) -> Option<Ordering> {
200        match self.len().cmp(&other.len()) {
201            Ordering::Equal => {
202                for (x, y) in self.iter().zip(other.iter()) {
203                    match x.partial_cmp(y) {
204                        Some(Ordering::Equal) => continue,
205                        cmp => return cmp,
206                    }
207                }
208                Some(Ordering::Equal)
209            }
210            cmp => Some(cmp),
211        }
212    }
213}
214
215impl<A> Ord for GapBuffer<A> where A: Ord {
216    #[inline]
217    fn cmp(&self, other: &GapBuffer<A>) -> Ordering {
218        match self.len().cmp(&other.len()) {
219            Ordering::Equal => {
220                for (x, y) in self.iter().zip(other.iter()) {
221                    match x.cmp(y) {
222                        Ordering::Equal => continue,
223                        cmp => return cmp,
224                    }
225                }
226                Ordering::Equal
227            }
228            cmp => cmp,
229        }
230    }
231}
232
233//FromIterator
234impl<A> FromIterator<A> for GapBuffer<A> {
235    fn from_iter<I: IntoIterator<Item=A>>(iterator: I) -> GapBuffer<A> {
236        let buf = iterator.into_iter().collect();
237        GapBuffer {
238            buf: buf,
239            offset: 0,
240        }
241    }
242}
243
244//Extend
245impl<A> Extend<A> for GapBuffer<A> {
246    fn extend<T: IntoIterator<Item=A>>(&mut self, iterator: T) {
247        let len = self.len();
248        // push_back inserts into the leftmost empty slot in the gap.
249        self.shift(len);
250        // So, extending the ring buffer directly at this point will have the same effect as
251        // repeated right insertions.  We don't need to modify the offset because the cursor stays
252        // in place.
253        self.buf.extend(iterator);
254    }
255}
256
257//Show
258impl<T> fmt::Debug for GapBuffer<T> where T: fmt::Debug {
259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260        try!(write!(f, "["));
261        let mut iter = self.iter();
262        if let Some(fst) = iter.next() {
263            try!(write!(f, "{:?}", fst));
264            for e in iter {
265                try!(write!(f, ",{:?}", e));
266            }
267        }
268        write!(f, "]")
269    }
270}
271
272impl<T> Index<usize> for GapBuffer<T> {
273    type Output = T;
274
275    #[inline]
276    fn index<'a>(&'a self, index: usize) -> &'a T {
277        let index = self.get_idx(index);
278        &self.buf[index]
279    }
280}
281
282impl<T> IndexMut<usize> for GapBuffer<T> {
283    #[inline]
284    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut T {
285        let index = self.get_idx(index);
286        &mut self.buf[index]
287    }
288}
289
290//### Iterator implementation. #####################################################################
291// Could likely be made more efficient since we know we're inbounds...
292#[derive(Clone)]
293pub struct Items<'a, T: 'a> {
294    buff: &'a GapBuffer<T>,
295    idx: usize,
296}
297
298impl<'a, T> Iterator for Items<'a, T> {
299    type Item = &'a T;
300
301    #[inline]
302    fn next(&mut self) -> Option<&'a T> {
303        let next = self.buff.get(self.idx);
304        if next.is_some() {
305            self.idx += 1;
306        }
307        next
308    }
309
310    #[inline]
311    fn size_hint(&self) -> (usize, Option<usize>) {
312        let len = self.buff.len();
313        (len, Some(len))
314    }
315}
316
317#[cfg(test)]
318mod tests {
319
320    use GapBuffer;
321
322    #[test]
323    fn test_init() {
324    //Test declaration & initialization
325        let test: GapBuffer<usize> = GapBuffer::with_capacity(100);
326        assert!(test.capacity() >= 100, "buffer initialized to {} capacity", test.capacity());
327        assert!(test.len() == 0, "Buffer initialized to {} length", test.len());
328
329    }
330
331    #[test]
332    fn test_insert() {
333        let mut test: GapBuffer<usize> = GapBuffer::new();
334
335        //Test insertion to end.
336        for x in range(0, 100) {
337            if x % 2 == 0 { test.insert(x/2, x); }
338        }
339        assert!(test.len() == 50, "After even insertions, buffer length is {}", test.len());
340
341        //Test insertion in the middle.
342        for x in range(0, 100) {
343            if x % 2 == 1 { test.insert(x, x); }
344        }
345        assert!(test.len() == 100, "After odd insertions, buffer length is {}", test.len());
346    }
347
348    #[test]
349    fn test_iter() {
350    //Test iteration.
351        let mut test: GapBuffer<usize> = GapBuffer::new();
352
353        for x in range(0, 100) {
354            test.insert(x,x);
355        }
356
357        let mut iterator = test.iter();
358        let mut index = range(0,100);
359        loop {
360            match (iterator.next(), index.next()) {
361                (Some(&x), Some(y)) => {
362                    assert!(x == y, "Element at index {} is {}", y, x);
363                }
364                (None, _) | (_, None) => { break }
365            }
366        }
367    }
368
369    #[test]
370    fn test_index() {
371    //Test indexing.
372        let mut test: GapBuffer<usize> = GapBuffer::new();
373
374        for x in range(0, 100) {
375            test.insert(x,x);
376        }
377
378        for x in range(0,100) {
379            assert!(test[x] == x, "Index {} failed", x);
380        }
381
382    }
383
384    #[test]
385    fn test_remove() {
386    //Test removal.
387
388        let mut test1: GapBuffer<usize> = GapBuffer::new();
389        let mut test2: GapBuffer<usize> = GapBuffer::new();
390
391        for x in range(0, 10) {
392            test1.insert(x,x);
393        }
394
395        for x in range(0,10) {
396            assert!(test1.remove(0) == Some(x), "Remove failed at {} (forward)", x);
397        }
398
399        test2.extend(0..5);
400        test2.remove(0);
401        for (i, &x) in test2.iter().enumerate() {
402            assert!(x == i + 1, "Remove test2 failed. Index {} is {}", x, i);
403        }
404
405    }
406}