3 * Copyright (C) 2004-2005 Novell, Inc
4 * Copyright (C) 2005 David Waite
5 * Copyright (C) 2007-2008 Jürg Billeter
6 * Copyright (C) 2009 Didier Villevalois
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Jürg Billeter <j@bitron.ch>
24 * Didier 'Ptitjes Villevalois <ptitjes@free.fr>
30 * Resizable array implementation of the {@link List} interface.
32 * The storage array grows automatically when needed.
34 * This implementation is pretty good for rarely modified data. Because they are
35 * stored in an array this structure does not fit for highly mutable data. For an
36 * alternative implementation see {@link LinkedList}.
40 public class Gee.ArrayList<G> : AbstractBidirList<G> {
44 public override int size {
51 public override bool read_only {
56 * The elements' equality testing function.
58 [CCode (notify = false)]
59 public EqualDataFunc<G> equal_func { private set; get; }
61 internal G[] _items = new G[4];
64 // concurrent modification protection
65 private int _stamp = 0;
68 * Constructs a new, empty array list.
70 * If not provided, the function parameter is requested to the
71 * {@link Functions} function factory methods.
73 * @param equal_func an optional element equality testing function
75 public ArrayList (owned EqualDataFunc<G>? equal_func = null) {
76 if (equal_func == null) {
77 equal_func = Functions.get_equal_func_for (typeof (G));
79 this.equal_func = equal_func;
85 public override Gee.Iterator<G> iterator () {
86 return new Iterator<G> (this);
92 public override ListIterator<G> list_iterator () {
93 return new Iterator<G> (this);
99 public override BidirListIterator<G> bidir_list_iterator () {
100 return new Iterator<G> (this);
106 public override bool contains (G item) {
107 return (index_of (item) != -1);
113 public override int index_of (G item) {
114 for (int index = 0; index < _size; index++) {
115 if (equal_func (_items[index], item)) {
125 public override G get (int index) {
127 assert (index < _size);
129 return _items[index];
135 public override void set (int index, G item) {
137 assert (index < _size);
139 _items[index] = item;
145 public override bool add (G item) {
146 if (_size == _items.length) {
149 _items[_size++] = item;
157 public override void insert (int index, G item) {
159 assert (index <= _size);
161 if (_size == _items.length) {
165 _items[index] = item;
172 public override bool remove (G item) {
173 for (int index = 0; index < _size; index++) {
174 if (equal_func (_items[index], item)) {
185 public override G remove_at (int index) {
187 assert (index < _size);
189 G item = _items[index];
190 _items[index] = null;
192 shift (index + 1, -1);
201 public override void clear () {
202 for (int index = 0; index < _size; index++) {
203 _items[index] = null;
212 public override List<G>? slice (int start, int stop) {
213 return_val_if_fail (start <= stop, null);
214 return_val_if_fail (start >= 0, null);
215 return_val_if_fail (stop <= _size, null);
217 var slice = new ArrayList<G> (this.equal_func);
218 for (int i = start; i < stop; i++) {
228 public bool add_all (Collection<G> collection) {
229 if (collection.is_empty) {
233 grow_if_needed (collection.size);
234 foreach (G item in collection) {
235 _items[_size++] = item;
241 private void shift (int start, int delta) {
243 assert (start <= _size);
244 assert (start >= -delta);
246 _items.move (start, start + delta, _size - start);
251 private void grow_if_needed (int new_count) {
252 assert (new_count >= 0);
254 int minimum_size = _size + new_count;
255 if (minimum_size > _items.length) {
256 // double the capacity unless we add even more items at this time
257 set_capacity (new_count > _items.length ? minimum_size : 2 * _items.length);
261 private void set_capacity (int value) {
262 assert (value >= _size);
264 _items.resize (value);
267 private class Iterator<G> : Object, Traversable<G>, Gee.Iterator<G>, BidirIterator<G>, ListIterator<G>, BidirListIterator<G> {
268 private ArrayList<G> _list;
269 private int _index = -1;
270 private bool _removed = false;
272 // concurrent modification protection
273 private int _stamp = 0;
275 public Iterator (ArrayList list) {
277 _stamp = _list._stamp;
280 public bool next () {
281 assert (_stamp == _list._stamp);
282 if (_index + 1 < _list._size) {
290 public bool has_next () {
291 assert (_stamp == _list._stamp);
292 return (_index + 1 < _list._size);
295 public bool first () {
296 assert (_stamp == _list._stamp);
297 if (_list.size == 0) {
305 public new G get () {
306 assert (_stamp == _list._stamp);
307 assert (_index >= 0);
308 assert (_index < _list._size);
310 return _list._items[_index];
313 public void remove () {
314 assert (_stamp == _list._stamp);
315 assert (_index >= 0);
316 assert (_index < _list._size);
318 _list.remove_at (_index);
321 _stamp = _list._stamp;
324 public bool previous () {
325 assert (_stamp == _list._stamp);
333 public bool has_previous () {
334 assert (_stamp == _list._stamp);
335 return (_index - 1 >= 0);
338 public bool last () {
339 assert (_stamp == _list._stamp);
340 if (_list.size == 0) {
343 _index = _list._size - 1;
347 public new void set (G item) {
348 assert (_stamp == _list._stamp);
349 assert (_index >= 0);
350 assert (_index < _list._size);
351 _list._items[_index] = item;
352 _stamp = ++_list._stamp;
355 public void insert (G item) {
356 assert (_stamp == _list._stamp);
357 assert (_index >= 0);
358 assert (_index < _list._size);
359 _list.insert (_index, item);
361 _stamp = _list._stamp;
364 public void add (G item) {
365 assert (_stamp == _list._stamp);
366 assert (_index >= 0);
367 assert (_index < _list._size);
368 _list.insert (_index + 1, item);
370 _stamp = _list._stamp;
373 public int index () {
374 assert (_stamp == _list._stamp);
375 assert (_index >= 0);
376 assert (_index < _list._size);
380 public bool read_only {
388 return _index >= 0 && _index < _list._size && ! _removed;
392 public void foreach (ForallFunc<G> f) {
393 assert (_stamp == _list._stamp);
394 if (_index < 0 || _removed)
396 while (_index < _list._size) {
397 f (_list._items[_index]);
400 _index = _list._size;