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; }
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 * Constructs a new array list based on provided array.
87 * If not provided, the function parameter is requested to the
88 * {@link Functions} function factory methods.
90 * @param items initial items to be put into array
91 * @param equal_func an optional element equality testing function
93 public ArrayList.wrap (owned G[] items, owned EqualDataFunc<G>? equal_func = null) {
94 if (equal_func == null) {
95 equal_func = Functions.get_equal_func_for (typeof (G));
97 this.equal_func = equal_func;
105 public override bool foreach(ForallFunc<G> f) {
106 for (int i = 0; i < _size; i++) {
107 if (!f (_items[i])) {
117 public override Gee.Iterator<G> iterator () {
118 return new Iterator<G> (this);
124 public override ListIterator<G> list_iterator () {
125 return new Iterator<G> (this);
131 public override BidirListIterator<G> bidir_list_iterator () {
132 return new Iterator<G> (this);
138 public override bool contains (G item) {
139 return (index_of (item) != -1);
145 public override int index_of (G item) {
146 for (int index = 0; index < _size; index++) {
147 if (equal_func (_items[index], item)) {
157 public override G get (int index) {
159 assert (index < _size);
161 return _items[index];
167 public override void set (int index, G item) {
169 assert (index < _size);
171 _items[index] = item;
177 public override bool add (G item) {
178 if (_size == _items.length) {
181 _items[_size++] = item;
189 public override void insert (int index, G item) {
191 assert (index <= _size);
193 if (_size == _items.length) {
197 _items[index] = item;
204 public override bool remove (G item) {
205 for (int index = 0; index < _size; index++) {
206 if (equal_func (_items[index], item)) {
217 public override G remove_at (int index) {
219 assert (index < _size);
221 G item = _items[index];
222 _items[index] = null;
224 shift (index + 1, -1);
233 public override void clear () {
234 for (int index = 0; index < _size; index++) {
235 _items[index] = null;
244 public override List<G>? slice (int start, int stop) {
245 return_val_if_fail (start <= stop, null);
246 return_val_if_fail (start >= 0, null);
247 return_val_if_fail (stop <= _size, null);
249 var slice = new ArrayList<G> (this.equal_func);
250 for (int i = start; i < stop; i++) {
260 public bool add_all (Collection<G> collection) {
261 if (collection.is_empty) {
265 grow_if_needed (collection.size);
266 collection.foreach ((item) => {_items[_size++] = item; return true;});
271 private void shift (int start, int delta) {
273 assert (start <= _size);
274 assert (start >= -delta);
276 _items.move (start, start + delta, _size - start);
281 private void grow_if_needed (int new_count) {
282 assert (new_count >= 0);
284 int minimum_size = _size + new_count;
285 if (minimum_size > _items.length) {
286 // double the capacity unless we add even more items at this time
287 set_capacity (new_count > _items.length ? minimum_size : 2 * _items.length);
291 private void set_capacity (int value) {
292 assert (value >= _size);
294 _items.resize (value);
297 private class Iterator<G> : Object, Traversable<G>, Gee.Iterator<G>, BidirIterator<G>, ListIterator<G>, BidirListIterator<G> {
298 private ArrayList<G> _list;
299 private int _index = -1;
300 private bool _removed = false;
302 // concurrent modification protection
303 private int _stamp = 0;
305 public Iterator (ArrayList list) {
307 _stamp = _list._stamp;
310 public bool next () {
311 assert (_stamp == _list._stamp);
312 if (_index + 1 < _list._size) {
320 public bool has_next () {
321 assert (_stamp == _list._stamp);
322 return (_index + 1 < _list._size);
325 public bool first () {
326 assert (_stamp == _list._stamp);
327 if (_list.size == 0) {
335 public new G get () {
336 assert (_stamp == _list._stamp);
337 assert (_index >= 0);
338 assert (_index < _list._size);
340 return _list._items[_index];
343 public void remove () {
344 assert (_stamp == _list._stamp);
345 assert (_index >= 0);
346 assert (_index < _list._size);
348 _list.remove_at (_index);
351 _stamp = _list._stamp;
354 public bool previous () {
355 assert (_stamp == _list._stamp);
363 public bool has_previous () {
364 assert (_stamp == _list._stamp);
365 return (_index - 1 >= 0);
368 public bool last () {
369 assert (_stamp == _list._stamp);
370 if (_list.size == 0) {
373 _index = _list._size - 1;
377 public new void set (G item) {
378 assert (_stamp == _list._stamp);
379 assert (_index >= 0);
380 assert (_index < _list._size);
381 _list._items[_index] = item;
382 _stamp = ++_list._stamp;
385 public void insert (G item) {
386 assert (_stamp == _list._stamp);
387 assert (_index >= 0);
388 assert (_index < _list._size);
389 _list.insert (_index, item);
391 _stamp = _list._stamp;
394 public void add (G item) {
395 assert (_stamp == _list._stamp);
396 assert (_index >= 0);
397 assert (_index < _list._size);
398 _list.insert (_index + 1, item);
400 _stamp = _list._stamp;
403 public int index () {
404 assert (_stamp == _list._stamp);
405 assert (_index >= 0);
406 assert (_index < _list._size);
410 public bool read_only {
418 return _index >= 0 && _index < _list._size && ! _removed;
422 public bool foreach (ForallFunc<G> f) {
423 assert (_stamp == _list._stamp);
424 if (_index < 0 || _removed) {
427 while (_index < _list._size) {
428 if (!f (_list._items[_index])) {
433 _index = _list._size - 1;